web-dev-qa-db-fra.com

Comprendre respectivement offsetWidth, clientWidth, scrollWidth et -Height

Il y a plusieurs questions sur StackOverflow concernant offsetWidth/clientWidth/scrollWidth (et -Height, respectivement), mais aucune ne donne d'explication complète sur la nature de ces valeurs.

En outre, il existe plusieurs sources sur le Web donnant des informations confuses ou incorrectes.

Pouvez-vous donner une explication complète incluant quelques conseils visuels? De plus, comment utiliser ces valeurs pour calculer la largeur des barres de défilement?

344
user123444555621

Le modèle de boîte CSS est plutôt compliqué, notamment en ce qui concerne le défilement de contenu. Alors que le navigateur utilise les valeurs de votre CSS pour dessiner des boîtes, la détermination de toutes les dimensions à l'aide de JS n'est pas simple si vous ne disposez que du CSS.

C'est pourquoi chaque élément possède six propriétés DOM pour votre commodité: offsetWidth, offsetHeight, clientWidth, clientHeight, scrollWidth et scrollHeight. Ce sont des attributs en lecture seule représentant la disposition visuelle actuelle, et tous sont des entiers (donc susceptibles d’erreurs d’arrondi).

Passons en revue en détail:

  • offsetWidth, offsetHeight: La taille de la zone de visualisation incluant toutes les bordures. Peut être calculé en ajoutant width/height, ainsi que des bourrages et des bordures, si l'élément a display: block
  • clientWidth, clientHeight: partie visuelle du contenu de la boîte, à l'exception des bordures et des barres de défilement, mais comprenant un remplissage. Ne peut pas être calculé directement à partir de CSS, dépend de la taille de la barre de défilement du système.
  • scrollWidth, scrollHeight: taille de tout le contenu de la boîte, y compris des pièces actuellement masquées en dehors de la zone de défilement. Ne peut être calculé directement à partir de CSS, dépend du contenu.

CSS2 Box Model

Essayez-le: jsFiddle


Puisque offsetWidth prend en compte la largeur de la barre de défilement, nous pouvons l’utiliser pour calculer la largeur de la barre de défilement via la formule

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

Malheureusement, des erreurs d’arrondi peuvent survenir, car offsetWidth et clientWidth sont toujours des entiers, alors que les tailles réelles peuvent être fractionnaires avec des niveaux de zoom autres que 1.

Notez que cela

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

not ​​fonctionne-t-il de manière fiable dans Chrome, étant donné que Chrome renvoie width avec la barre de défilement déjà soustraite. (De plus, Chrome rend le paddingBottom au bas du contenu du défilement, contrairement aux autres navigateurs)

789
user123444555621

J'ai créé une version plus complète et plus propre que certaines personnes pourraient trouver utile pour rappeler quel nom correspond à quelle valeur. J'ai utilisé Chrome le code de couleur de Dev Tool et ses étiquettes sont organisées symétriquement pour faciliter la lecture des analogies:

enter image description here

  • Remarque 1: clientLeft inclut également la largeur de la barre de défilement verticale si la direction du texte est réglée de droite à gauche (car la barre est affichée à gauche dans ce cas).

  • Remarque 2: la ligne la plus à l'extérieur représente le parent le plus proche (un élément dont position propriété est définie sur une valeur différente de static ou initial). Ainsi, si le conteneur direct n'est pas un élément positionné , la ligne ne représente pas le premier conteneur de la hiérarchie mais un autre élément plus élevé dans la hiérarchie. Si aucun positionné parent n'est trouvé, le navigateur utilisera la html ou body élément comme référence


J'espère que quelqu'un le trouvera utile, juste mes 2 centimes;)

40
Lual

Si vous souhaitez utiliser scrollWidth pour obtenir le "REAL" CONTENU LARGEUR/HAUTEUR (car le contenu peut être plus grand que la largeur/hauteur-Box définie par css) le scrollWidth/Height est très INCRELABLE comme certains navigateurs semblent " MOVE "the paddingRIGHT & paddingBOTTOM si le contenu est trop volumineux. Ils placent ensuite les rembourrages à DROITE/INFÉRIEUR du "contenu trop large/trop élevé" (voir l'image ci-dessous).

==> Par conséquent, pour obtenir la taille réelle du contenu de certains navigateurs, vous devez soustraire les DEUX rembourrages de la largeur de défilement et, dans certains navigateurs, vous devez uniquement soustraire le Rembourrage GAUCHE.

J'ai trouvé une solution pour cela et je voulais l'ajouter comme commentaire, mais cela n'a pas été autorisé. J'ai donc pris la photo et l'ai rendue un peu plus claire en ce qui concerne les "rembourrages déplacés" et le "manque de fiabilité scrollWidth". Dans la ZONE BLEUE, vous trouverez ma solution pour obtenir la largeur de contenu "réel"

J'espère que cela aide à rendre les choses encore plus claires!

enter image description here

30
Manny_user3297459

Il existe un bon article sur MDN qui explique la théorie qui sous-tend ces concepts: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements

Il explique également les différences conceptuelles importantes entre la largeur/hauteur de boundingClientRect et offsetWidth/offsetHeight.

Ensuite, pour prouver que la théorie est vraie ou fausse, vous avez besoin de tests. C'est ce que j'ai fait ici: https://github.com/lingtalfi/dimensions-cheatsheet

Il teste chrome53, ff49, safari9, edge13 et ie11.

Les résultats des tests prouvent que la théorie est généralement juste. Pour les tests, j’ai créé 3 divs contenant chacun 10 paragraphes lorem ipsum. Quelques css leur ont été appliqués:

.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);
}

Et voici les résultats:

  • div1

    • offsetWidth: 530 (chrome53, ff49, safari9, Edge13, ie11)
    • offsetHeight: 330 (chrome53, ff49, safari9, edge13, ie11)
    • largeur: 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)
    • largeur bcr: 500 (chrome53, ff49, safari9, edge13, ie11)
    • hauteur: 300 (chrome53, ff49, safari9)
    • hauteur: 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)
    • largeur: 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)

Ainsi, mis à part la valeur de hauteur de boundingClientRect (299.9999694824219 au lieu de 300 attendus) dans Edge13 et ie11, les résultats confirment que la théorie derrière cela fonctionne.

À partir de là, voici ma définition de ces concepts:

  • offsetWidth/offsetHeight: dimensions de la boîte de bordure de présentation
  • boundingClientRect: dimensions de la boîte de rendu
  • clientWidth/clientHeight: dimensions de la partie visible de la zone de remplissage de la présentation (à l'exception des barres de défilement)
  • scrollWidth/scrollHeight: dimensions de la zone de remplissage de la disposition si elle n'était pas contrainte par des barres de défilement

Remarque: la largeur de la barre de défilement verticale par défaut est 12px sous Edge13, 15px sous chrome53, ff49 et safari9 et 17px sous ie11 (effectuée à l'aide de mesures dans photoshop à partir de captures d'écran et attestée par les résultats des tests).

Cependant, dans certains cas, votre application n'utilise peut-être pas la largeur de la barre de défilement verticale par défaut.

Donc, étant donné les définitions de ces concepts, la largeur de la barre de défilement verticale doit être égale à (en pseudo-code):

Notez que si vous ne comprenez pas la disposition vs le rendu, veuillez lire l’article mdn.

De plus, si vous avez un autre navigateur (ou si vous voulez voir les résultats des tests par vous-même), vous pouvez voir ma page de test ici: --- (http://codepen.io/lingtalfi/pen/BLdBdL =

12
ling