Comprensione di offsetWidth, clientWidth, scrollWidth e -Height, rispettivamente


385

Esistono diverse domande su StackOverflow per quanto riguarda offsetWidth / clientWidth / scrollWidth (e -Height, rispettivamente), ma nessuna fornisce una spiegazione completa di quali siano questi valori.

Inoltre, ci sono diverse fonti sul web che forniscono informazioni confuse o errate.

Puoi dare una spiegazione completa includendo alcuni suggerimenti visivi? Inoltre, come si possono usare questi valori per calcolare la larghezza della barra di scorrimento?

Risposte:


869

Il modello di box CSS è piuttosto complicato, in particolare quando si tratta di scorrere i contenuti. Mentre il browser utilizza i valori del CSS per disegnare caselle, determinare tutte le dimensioni utilizzando JS non è semplice se si dispone solo del CSS.

Ecco perché ogni elemento è dotato di sei proprietà DOM per la vostra convenienza: offsetWidth, offsetHeight, clientWidth, clientHeight, scrollWidthe scrollHeight. Questi sono attributi di sola lettura che rappresentano il layout visivo corrente e tutti sono numeri interi (quindi possibilmente soggetti a errori di arrotondamento).

Analizziamoli in dettaglio:

  • offsetWidth, offsetHeight: La dimensione della casella visiva che include tutti i bordi. Può essere calcolato aggiungendo width/ heighte padding e bordi, se l'elemento hadisplay: block
  • clientWidth, clientHeight: La parte visiva del contenuto della casella, esclusi i bordi o le barre di scorrimento, ma include il riempimento. Non può essere calcolato direttamente dal CSS, dipende dalla dimensione della barra di scorrimento del sistema.
  • scrollWidth, scrollHeight: La dimensione di tutto il contenuto della scatola, comprese le parti che sono attualmente nascoste al di fuori dell'area di scorrimento. Non può essere calcolato direttamente dal CSS, dipende dal contenuto.

Modello di scatola CSS2

Provalo: jsFiddle


Poiché offsetWidthtiene conto della larghezza della barra di scorrimento, possiamo usarla per calcolare la larghezza della barra di scorrimento tramite la formula

scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth

Sfortunatamente, potremmo avere errori di arrotondamento, poiché offsetWidthe clientWidthsono sempre numeri interi, mentre le dimensioni effettive potrebbero essere frazionarie con livelli di zoom diversi da 1.

Si noti che questo

scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth

non non funzionare in modo affidabile in Chrome, dal momento che i rendimenti Chrome widthcon barra di scorrimento già sottratto. (Inoltre, Chrome esegue il rendering del paddingBottom nella parte inferiore del contenuto dello scorrimento, mentre altri browser no)


27
Per coloro che cercano una granularità più fine rispetto ai numeri interi, utilizzare element.getBoundingClientRect()(vedere la nota su developer.mozilla.org/en-US/docs/Web/API/Element.clientWidth )
Anson Kao,

1
Nota che, a seconda del layout, scrollWidth e scrollHeight possono essere davvero utili per ottenere la dimensione dei tuoi pseudo elementi :: before e :: after.
David

Inoltre, sarebbe utile spiegare come si relazionano naturalWidthenaturalHeight
YakovL l'

perché scrollHeightinclude padding-bottomma scrollWidthnon includepadding-right
JunGor

clientWidthper document.documentElement.clientWidthè diverso come sembra includere il padding, bordersemargin
Drenai

50

Ho creato una versione più completa e più pulita che alcune persone potrebbero trovare utili per ricordare quale nome corrisponde a quale valore. Ho usato il codice colore di Chrome Dev Tool e le etichette sono organizzate simmetricamente per raccogliere le analogie più velocemente:

inserisci qui la descrizione dell'immagine

  • Nota 1: clientLeftinclude anche la larghezza della barra di scorrimento verticale se la direzione del testo è impostata da destra a sinistra (poiché in questo caso la barra viene visualizzata a sinistra)

  • Nota 2: la linea più esterna rappresenta il genitore posizionato più vicino (un elemento la cui positionproprietà è impostata su un valore diverso da statico initial). Pertanto, se il contenitore diretto non è un elemento posizionato , la linea non rappresenta il primo contenitore nella gerarchia ma un altro elemento più in alto nella gerarchia. Se non viene trovato alcun genitore posizionato , il browser prenderà l' elemento htmlo bodycome riferimento


Spero che qualcuno lo trovi utile, solo i miei 2 centesimi;)


30

Se si desidera utilizzare scrollWidth per ottenere LARGHEZZA / ALTEZZA DEL CONTENUTO "REALE" (poiché il contenuto può essere più GRANDE della larghezza / altezza-box definiti dal css), scrollWidth / Height è molto INREDIBILE poiché alcuni browser sembrano "SPOSTARE" il paddingRIGHT & paddingBOTTOM se il contenuto è troppo grande. Quindi posizionano le imbottiture sul lato DESTRO / INFERIORE del "contenuto troppo ampio / alto" (vedi immagine sotto).

==> Pertanto, per ottenere la LARGHEZZA DEI CONTENUTI REALI in alcuni browser è necessario sottrarre ENTRAMBI i padding dalla larghezza di scorrimento e in alcuni browser è necessario sottrarre solo il padding LEFT.

Ho trovato una soluzione per questo e volevo aggiungerlo come commento, ma non mi è stato permesso. Così ho scattato la foto e l'ho resa un po 'più chiara per quanto riguarda i "padding spostati" e la "scrollWidth inaffidabile". Nell'AREA BLU trovi la mia soluzione su come ottenere la LARGHEZZA DEI CONTENUTI "REALI"!

Spero che questo aiuti a rendere le cose ancora più chiare!

inserisci qui la descrizione dell'immagine


13

C'è un buon articolo su MDN che spiega la teoria alla base di questi concetti: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements

Spiega anche le importanti differenze concettuali tra larghezza / altezza di boundingClientRect rispetto a offsetWidth / offsetHeight.

Quindi, per dimostrare la teoria giusta o sbagliata, hai bisogno di alcuni test. Questo è quello che ho fatto qui: https://github.com/lingtalfi/dimensions-cheatsheet

È in fase di test per chrome53, ff49, safari9, edge13 e ie11.

I risultati dei test dimostrano che la teoria è generalmente corretta. Per i test, ho creato 3 div contenenti 10 paragrafi di lorem ipsum ciascuno. Alcuni CSS sono stati applicati a loro:

.div1{
    width: 500px;
    height: 300px;
    padding: 10px;
    border: 5px solid black;
    overflow: auto;
}
.div2{
    width: 500px;
    height: 300px;
    padding: 10px;
    border: 5px solid black;
    box-sizing: border-box;
    overflow: auto;
}

.div3{
    width: 500px;
    height: 300px;
    padding: 10px;
    border: 5px solid black;
    overflow: auto;
    transform: scale(0.5);
}

E qui ci sono i risultati:

  • div1

    • offsetWidth: 530 (chrome53, ff49, safari9, edge13, ie11)
    • offsetHeight: 330 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.width: 530 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.height: 330 (chrome53, ff49, safari9, edge13, ie11)

    • clientWidth: 505 (chrome53, ff49, safari9)

    • clientWidth: 508 (edge13)
    • clientWidth: 503 (ie11)
    • clientHeight: 320 (chrome53, ff49, safari9, edge13, ie11)

    • scrollWidth: 505 (chrome53, safari9, ff49)

    • scrollWidth: 508 (edge13)
    • scrollWidth: 503 (ie11)
    • scrollHeight: 916 (chrome53, safari9)
    • scrollHeight: 954 (ff49)
    • scrollHeight: 922 (edge13, ie11)
  • div2

    • offsetWidth: 500 (chrome53, ff49, safari9, edge13, ie11)
    • offsetHeight: 300 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.width: 500 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.height: 300 (chrome53, ff49, safari9)
    • bcr. altezza: 299.9999694824219 (edge13, ie11)
    • clientWidth: 475 (chrome53, ff49, safari9)
    • clientWidth: 478 (edge13)
    • clientWidth: 473 (ie11)
    • clientHeight: 290 (chrome53, ff49, safari9, edge13, ie11)

    • scrollWidth: 475 (chrome53, safari9, ff49)

    • scrollWidth: 478 (edge13)
    • scrollWidth: 473 (ie11)
    • scrollHeight: 916 (chrome53, safari9)
    • scrollHeight: 954 (ff49)
    • scrollHeight: 922 (edge13, ie11)
  • div3

    • offsetWidth: 530 (chrome53, ff49, safari9, edge13, ie11)
    • offsetHeight: 330 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.width: 265 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.height: 165 (chrome53, ff49, safari9, edge13, ie11)
    • clientWidth: 505 (chrome53, ff49, safari9)
    • clientWidth: 508 (edge13)
    • clientWidth: 503 (ie11)
    • clientHeight: 320 (chrome53, ff49, safari9, edge13, ie11)

    • scrollWidth: 505 (chrome53, safari9, ff49)

    • scrollWidth: 508 (edge13)
    • scrollWidth: 503 (ie11)
    • scrollHeight: 916 (chrome53, safari9)
    • scrollHeight: 954 (ff49)
    • scrollHeight: 922 (edge13, ie11)

Quindi, a parte il valore di altezza di boundingClientRect (299.9999694824219 invece di 300 previsti) in edge13 e ie11, i risultati confermano che la teoria alla base di questo funziona.

Da lì, ecco la mia definizione di quei concetti:

  • offsetWidth / offsetHeight: dimensioni della casella del bordo del layout
  • boundingClientRect: dimensioni della casella del bordo di rendering
  • clientWidth / clientHeight: dimensioni della parte visibile del riquadro di riempimento del layout (escluse le barre di scorrimento)
  • scrollWidth / scrollHeight: dimensioni della casella di riempimento del layout se non era vincolata dalle barre di scorrimento

Nota: la larghezza della barra di scorrimento verticale predefinita è 12px in edge13, 15px in chrome53, ff49 e safari9 e 17px in ie11 (eseguita dalle misurazioni in Photoshop da schermate e dimostrata dai risultati dei test).

Tuttavia, in alcuni casi, forse l'app non utilizza la larghezza della barra di scorrimento verticale predefinita.

Quindi, date le definizioni di quei concetti, la larghezza della barra di scorrimento verticale dovrebbe essere uguale (in pseudo codice):

  • dimensione layout: offsetWidth - clientWidth - (borderLeftWidth + borderRightWidth)

  • dimensione di rendering: boundingClientRect.width - clientWidth - (borderLeftWidth + borderRightWidth)

Nota, se non capisci il layout rispetto al rendering, leggi l'articolo mdn.

Inoltre, se hai un altro browser (o se vuoi vedere tu stesso i risultati dei test), puoi vedere la mia pagina di test qui: http://codepen.io/lingtalfi/pen/BLdBdL

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.