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?
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.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)
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:
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;)
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!
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
bcr.height: 330 (chrome53, ff49, safari9, edge13, ie11)
clientWidth: 505 (chrome53, ff49, safari9)
clientHeight: 320 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth: 505 (chrome53, safari9, ff49)
div2
clientHeight: 290 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth: 475 (chrome53, safari9, ff49)
div3
clientHeight: 320 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth: 505 (chrome53, safari9, ff49)
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:
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):
dimension de présentation: offsetWidth - clientWidth borderLeftWidth + borderRightWidth)
dimension de rendu: boundingClientRect.width - clientWidth - (borderLeftWidth + borderRightWidth)
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 =