Come recuperare la larghezza e l'altezza effettive di un elemento HTML?


895

Supponiamo di avere un oggetto <div>che desidero centrare nel display del browser (viewport). Per fare ciò, devo calcolare la larghezza e l'altezza <div>dell'elemento.

Cosa dovrei usare? Si prega di includere informazioni sulla compatibilità del browser.


9
Tieni presente che ottenere l'altezza di un elemento attraverso qualsiasi metodo ha sempre un impatto sulle prestazioni in quanto consente al browser di ricalcolare la posizione di tutti gli elementi nella pagina (ridisposizione). Pertanto, evitare di farlo troppo. Dai un'occhiata a questo elenco per sapere che tipo di cose attivano un riflusso.
Marcelo Lazaroni,

Risposte:


1288

È necessario utilizzare le proprietà .offsetWidthe .offsetHeight. Nota che appartengono all'elemento, no .style.

var width = document.getElementById('foo').offsetWidth;

La funzione.getBoundingClientRect() restituisce dimensioni e posizione dell'elemento come numeri in virgola mobile dopo aver eseguito trasformazioni CSS.

> console.log(document.getElementById('id').getBoundingClientRect())
DOMRect {
    bottom: 177,
    height: 54.7,
    left: 278.5,​
    right: 909.5,
    top: 122.3,
    width: 631,
    x: 278.5,
    y: 122.3,
}

174
Attenzione! offsetHeight / offsetWidth può restituire 0 se hai apportato alcune modifiche DOM all'elemento di recente. Potrebbe essere necessario chiamare questo codice in una chiamata setTimeout dopo aver modificato l'elemento.
Dan Fabulich,


31
In quali circostanze restituisce 0?
Ghepardo,

46
@JDandChips: offsetWidthsarà 0 se l'elemento è display:none, mentre il calcolo widthpotrebbe ancora avere un valore positivo in questa istanza. visibility:hiddennon influisce sul offsetWidth.
MrWhite,

21
@Supuhstar hanno entrambi significati diversi. offsetWidthrestituisce la casella "intera" che include contenuto, riempimento e bordi; while clientWidthrestituisce la sola dimensione della casella del contenuto (quindi avrà un valore più piccolo ogni volta che l'elemento ha una spaziatura e / o bordo diversi da zero). (mod a cura di chiarezza)
Edurne Pascual,

200

Dai un'occhiata Element.getBoundingClientRect().

Questo metodo restituirà un oggetto contenente width, heighte alcuni altri valori utili:

{
    width: 960,
    height: 71,
    top: 603,
    bottom: 674,
    left: 360,
    right: 1320
}

Per esempio:

var element = document.getElementById('foo');
var positionInfo = element.getBoundingClientRect();
var height = positionInfo.height;
var width = positionInfo.width;

Credo che questo non abbia i problemi che .offsetWidthe .offsetHeightfanno dove a volte ritornano 0(come discusso nei commenti qui )

Un'altra differenza è che getBoundingClientRect()può restituire pixel frazionari, dove .offsetWidthe .offsetHeightarrotonderà all'intero più vicino.

Nota IE8 : getBoundingClientRectnon restituisce altezza e larghezza su IE8 e precedenti. *

Se è necessario supportare IE8, utilizzare .offsetWidthe .offsetHeight:

var height = element.offsetHeight;
var width = element.offsetWidth;

Vale la pena notare che l'oggetto restituito da questo metodo non è in realtà un oggetto normale . Le sue proprietà non sono enumerabili (quindi, ad esempio, Object.keysnon funziona immediatamente).

Maggiori informazioni qui: come convertire un ClientRect / DomRect in un oggetto semplice

Riferimento:


8
getboundingClientRect () restituirà la larghezza e l'altezza effettiva degli elementi scalati via css considerando offsetHeighte offsetWidthnon.
Luca

66

NOTA : questa risposta è stata scritta nel 2008. All'epoca la migliore soluzione cross-browser per la maggior parte delle persone era usare jQuery. Lascio qui la risposta per i posteri e, se stai usando jQuery, questo è un buon modo per farlo. Se stai usando qualche altro framework o JavaScript puro, la risposta accettata è probabilmente la strada da percorrere.

Come di jQuery 1.2.6 è possibile utilizzare una delle principali funzioni CSS , heighte width(o outerHeighte outerWidth, a seconda dei casi).

var height = $("#myDiv").height();
var width = $("#myDiv").width();

var docHeight = $(document).height();
var docWidth = $(document).width();

45

Nel caso fosse utile a chiunque, ho messo una casella di testo, un pulsante e div tutto con lo stesso css:

width:200px;
height:20px;
border:solid 1px #000;
padding:2px;

<input id="t" type="text" />
<input id="b" type="button" />
<div   id="d"></div>

L'ho provato in Chrome, Firefox e ie-Edge, l'ho provato con jquery e senza, e l'ho provato con e senza box-sizing:border-box. Sempre con<!DOCTYPE html>

I risultati:

                                                               Firefox       Chrome        IE-Edge    
                                                              with   w/o    with   w/o    with   w/o     box-sizing

$("#t").width()                                               194    200    194    200    194    200
$("#b").width()                                               194    194    194    194    194    194
$("#d").width()                                               194    200    194    200    194    200

$("#t").outerWidth()                                          200    206    200    206    200    206
$("#b").outerWidth()                                          200    200    200    200    200    200
$("#d").outerWidth()                                          200    206    200    206    200    206

$("#t").innerWidth()                                          198    204    198    204    198    204
$("#b").innerWidth()                                          198    198    198    198    198    198
$("#d").innerWidth()                                          198    204    198    204    198    204

$("#t").css('width')                                          200px  200px  200px  200px  200px  200px
$("#b").css('width')                                          200px  200px  200px  200px  200px  200px
$("#d").css('width')                                          200px  200px  200px  200px  200px  200px

$("#t").css('border-left-width')                              1px    1px    1px    1px    1px    1px
$("#b").css('border-left-width')                              1px    1px    1px    1px    1px    1px
$("#d").css('border-left-width')                              1px    1px    1px    1px    1px    1px

$("#t").css('padding-left')                                   2px    2px    2px    2px    2px    2px
$("#b").css('padding-left')                                   2px    2px    2px    2px    2px    2px
$("#d").css('padding-left')                                   2px    2px    2px    2px    2px    2px

document.getElementById("t").getBoundingClientRect().width    200    206    200    206    200    206
document.getElementById("b").getBoundingClientRect().width    200    200    200    200    200    200
document.getElementById("d").getBoundingClientRect().width    200    206    200    206    200    206

document.getElementById("t").offsetWidth                      200    206    200    206    200    206
document.getElementById("b").offsetWidth                      200    200    200    200    200    200
document.getElementById("d").offsetWidth                      200    206    200    206    200    206

1
Giusto per essere chiari ... qualcuno di questi browser fa qualcosa di diverso l'uno dall'altro? Non riesco a trovare alcuna differenza ... Inoltre, io non sono down-voto (ancora), ma questo non realmente rispondere direttamente alla domanda, anche se potrebbe essere facilmente Editted a farlo.
Zach Lysobey,

1
Non aveva lo scopo di rispondere alla domanda: ha già ricevuto risposta. Solo alcune informazioni utili e sì, tutti i principali browser della versione più recente concordano su questi valori, il che è positivo.
Graham,

3
Bene ... se il tuo intento non è quello di rispondere alla domanda, allora questo non appartiene davvero qui (come "risposta"). Vorrei prendere in considerazione l'idea di inserirlo in una risorsa esterna (forse un elemento GitHub o un post di blog) e collegarlo in un commento sulla domanda originale o su una delle risposte.
Zach Lysobey,

21
@ZachLysobey Ci sono eccezioni ad ogni regola - e questa è una cosa interessante e utile da vedere.
Dan Nissenbaum,

16

Secondo MDN: Determinazione delle dimensioni degli elementi

offsetWidthe offsetHeightrestituisce la "quantità totale di spazio occupato da un elemento, inclusa la larghezza del contenuto visibile, le barre di scorrimento (se presenti), il riempimento e il bordo"

clientWidthe clientHeightrestituisce "quanto spazio occupa il contenuto effettivamente visualizzato, incluso il riempimento ma non il bordo, i margini o le barre di scorrimento"

scrollWidthe scrollHeightrestituisce la "dimensione effettiva del contenuto, indipendentemente da quanto è attualmente visibile"

Quindi dipende dal fatto che il contenuto misurato dovrebbe essere fuori dall'area visualizzabile corrente.


5

Devi solo calcolarlo per IE7 e versioni precedenti (e solo se i tuoi contenuti non hanno dimensioni fisse). Suggerisco di utilizzare i commenti condizionali HTML per limitare l'hack ai vecchi IE che non supportano CSS2. Per tutti gli altri browser utilizzare questo:

<style type="text/css">
    html,body {display:table; height:100%;width:100%;margin:0;padding:0;}
    body {display:table-cell; vertical-align:middle;}
    div {display:table; margin:0 auto; background:red;}
</style>
<body><div>test<br>test</div></body>

Questa è la soluzione perfetta. Centra <div>di qualsiasi dimensione e lo restringe a dimensioni del suo contenuto.


3

È facile modificare gli stili degli elementi ma è difficile leggere il valore.

JavaScript non è in grado di leggere alcuna proprietà di stile dell'elemento (elem.style) proveniente da CSS (interno / esterno) a meno che non si usi la chiamata al metodo integrata getComputedStyle in javascript.

getComputedStyle (element [, pseudo])

Elemento: l'elemento per cui leggere il valore.
pseudo: uno pseudo-elemento, se necessario, ad esempio :: before. Una stringa vuota o nessun argomento indica l'elemento stesso.

Il risultato è un oggetto con proprietà di stile, come elem.style, ma ora rispetto a tutte le classi css.

Ad esempio, qui lo stile non vede il margine:

<head>
  <style> body { color: red; margin: 5px } </style>
</head>
<body>

  <script>
    let computedStyle = getComputedStyle(document.body);

    // now we can read the margin and the color from it

    alert( computedStyle.marginTop ); // 5px
    alert( computedStyle.color ); // rgb(255, 0, 0)
  </script>

</body>

Quindi modificato il codice javaScript per includere getComputedStyle dell'elemento che si desidera ottenere larghezza / altezza o altro attributo

window.onload = function() {

    var test = document.getElementById("test");
    test.addEventListener("click", select);


    function select(e) {                                  
        var elementID = e.target.id;
        var element = document.getElementById(elementID);
        let computedStyle = getComputedStyle(element);
        var width = computedStyle.width;
        console.log(element);
        console.log(width);
    }

}

Valori calcolati e risolti

Ci sono due concetti nei CSS:

Un valore di stile calcolato è il valore dopo l'applicazione di tutte le regole CSS e dell'ereditarietà CSS, come risultato della cascata CSS. Può apparire come altezza: 1em o dimensione carattere: 125%.

Un valore di stile risolto è quello finalmente applicato all'elemento. Valori come 1em o 125% sono relativi. Il browser prende il valore calcolato e rende tutte le unità fisse e assolute, ad esempio: altezza: 20 px o dimensione del carattere: 16 px. Per le proprietà della geometria, i valori risolti possono avere un punto mobile, ad esempio larghezza: 50,5 px.

Molto tempo fa getComputedStyle è stato creato per ottenere valori calcolati, ma si è scoperto che i valori risolti sono molto più convenienti e lo standard è cambiato.
Quindi oggigiorno getComputedStyle restituisce effettivamente il valore risolto della proprietà.

Notare che:

getComputedStyle richiede il nome completo della proprietà

Dovresti sempre chiedere la proprietà esatta che desideri, come imbottitura Sinistra o altezza o larghezza. In caso contrario, il risultato corretto non è garantito.

Ad esempio, se ci sono proprietà paddingLeft / paddingTop, cosa dovremmo ottenere per getComputedStyle (elem) .padding? Niente o forse un valore "generato" da padding noti? Non esiste una regola standard qui.

Ci sono altre incongruenze. Ad esempio, alcuni browser (Chrome) mostrano 10px nel documento seguente, e alcuni di essi (Firefox) - non:

<style>
  body {
    margin: 30px;
    height: 900px;
  }
</style>
<script>
  let style = getComputedStyle(document.body);
  alert(style.margin); // empty string in Firefox
</script>

per maggiori informazioni https://javascript.info/styles-and-classes


1

element.offsetWidth ed element.offsetHeight dovrebbero fare, come suggerito nel post precedente.

Tuttavia, se vuoi solo centrare il contenuto, c'è un modo migliore per farlo. Supponendo di utilizzare xhtml DOCTYPE rigoroso. imposta il margine: 0, proprietà automatica e larghezza richiesta in px sul tag body. Il contenuto viene allineato al centro della pagina.


1
Penso che voglia centrarlo anche verticalmente, il che è una vera seccatura con i CSS a meno che tu non possa soddisfare alcuni criteri specifici (ad esempio contenuti di dimensioni note)
Greg,

1

... sembra che CSS aiuti a mettere al centro il div ...

<style>
 .monitor {
 position:fixed;/* ... absolute possible if on :root */
 top:0;bottom:0;right:0;left:0;
 visibility:hidden;
 }
 .wrapper {
 width:200px;/* this is size range */
 height:100px;
 position:absolute;
 left:50%;top:50%;
 visibility:hidden;
 }

 .content {
 position:absolute;
 width: 100%;height:100%;
 left:-50%;top:-50%;
 visibility:visible;
 }

</style>

 <div class="monitor">
  <div class="wrapper">
   <div class="content">

 ... so you hav div 200px*100px on center ...

  </div>
 </div>
</div>

0

anche tu puoi usare questo codice:

var divID = document.getElementById("divid");

var h = divID.style.pixelHeight;

1
Hmm, funziona in Chrome e IE9, non sembra funzionare in Firefox. Funziona solo con determinati tipi di documenti?
BrainSlugs83,

1
pixelHeight era un'invenzione di Internet Explorer che non deve essere più utilizzato stackoverflow.com/q/17405066/2194590
HolgerJeromin

0

se è necessario centrarlo nella porta di visualizzazione del browser; puoi ottenerlo solo con CSS

yourSelector {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
} 

-2

Ecco il codice per WKWebView che determina l'altezza dell'elemento Dom specifico (non funziona correttamente per l'intera pagina)

let html = "<body><span id=\"spanEl\" style=\"font-family: '\(taskFont.fontName)'; font-size: \(taskFont.pointSize - 4.0)pt; color: rgb(\(red), \(blue), \(green))\">\(textValue)</span></body>"
webView.navigationDelegate = self
webView.loadHTMLString(taskHTML, baseURL: nil)

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.evaluateJavaScript("document.getElementById(\"spanEl\").getBoundingClientRect().height;") { [weak self] (response, error) in
        if let nValue = response as? NSNumber {

        }
    }
}

solo per essere chiari, questo è il swiftcodice iOS , giusto? Non JavaScript. Sto ritirando un downvote (questo potrebbe effettivamente essere molto utile) ma tieni presente che questo non risponde alla domanda e probabilmente sarebbe più appropriato su un'altra domanda specifica di iOS. Se non ne esiste già uno, forse prendere in considerazione la possibilità di chiedere una risposta autonoma.
Zach Lysobey,

-3

Se offsetWidth restituisce 0, è possibile ottenere la proprietà di larghezza dello stile dell'elemento e cercarlo per un numero. "100px" -> 100

/\d*/.exec(MyElement.style.width)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.