Das CSS-Box-Modell ist ziemlich kompliziert, insbesondere wenn es um das Scrollen von Inhalten geht. Während der Browser die Werte aus Ihrem CSS zum Zeichnen von Feldern verwendet, ist das Bestimmen aller Dimensionen mit JS nicht einfach, wenn Sie nur über das CSS verfügen.
Das ist , warum jedes Element sechs DOM - Eigenschaften für Ihre Bequemlichkeit hat: offsetWidth
, offsetHeight
, clientWidth
, clientHeight
, scrollWidth
und scrollHeight
. Dies sind schreibgeschützte Attribute, die das aktuelle visuelle Layout darstellen, und alle sind Ganzzahlen (daher können Rundungsfehler auftreten).
Lassen Sie uns sie im Detail durchgehen:
offsetWidth
, offsetHeight
: Die Größe der visuellen Box mit allen Rändern. Kann durch Hinzufügen von width
/ height
und Auffüllungen und Rahmen berechnet werden , wenn das Element hatdisplay: block
clientWidth
, clientHeight
: Der visuelle Teil des Boxinhalts, ohne Rahmen oder Bildlaufleisten, aber mit Auffüllung. Kann nicht direkt aus CSS berechnet werden, hängt von der Größe der Bildlaufleiste des Systems ab.
scrollWidth
, scrollHeight
: Die Größe des gesamten Inhalts der Box, einschließlich der Teile, die derzeit außerhalb des Bildlaufbereichs verborgen sind. Kann nicht direkt aus CSS berechnet werden, hängt vom Inhalt ab.
Probieren Sie es aus: jsFiddle
Da offsetWidth
die Breite der Bildlaufleiste berücksichtigt wird, können wir damit die Breite der Bildlaufleiste über die Formel berechnen
scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth
Leider können Rundungsfehler auftreten, da offsetWidth
und clientWidth
immer ganze Zahlen sind, während die tatsächlichen Größen mit anderen Zoomstufen als 1 gebrochen sein können.
Beachten Sie, dass dies
scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth
funktioniert in Chrome nicht zuverlässig, da Chrome width
mit bereits abgezogener Bildlaufleiste zurückkehrt. (Außerdem rendert Chrome paddingBottom am unteren Rand des Bildlaufinhalts, während andere Browser dies nicht tun.)
element.getBoundingClientRect()
(siehe Hinweis unter developer.mozilla.org/en-US/docs/Web/API/Element.clientWidth )naturalWidth
und beziehennaturalHeight
scrollHeight
enthältpadding-bottom
,scrollWidth
aber nicht enthaltenpadding-right
clientWidth
fürdocument.documentElement.clientWidth
anders als es die gehören scheintpadding
,borders
undmargin
Ich habe eine umfassendere und übersichtlichere Version erstellt, die einige Leute möglicherweise nützlich finden, um sich daran zu erinnern, welcher Name welchem Wert entspricht. Ich habe den Farbcode von Chrome Dev Tool verwendet und die Beschriftungen sind symmetrisch angeordnet, um Analogien schneller zu erkennen:
Hinweis 1:
clientLeft
Enthält auch die Breite der vertikalen Bildlaufleiste, wenn die Richtung des Texts von rechts nach links eingestellt ist (da die Leiste in diesem Fall links angezeigt wird).Hinweis 2: Die äußerste Linie repräsentiert das am nächsten positionierte übergeordnete Element (ein Element, dessen
position
Eigenschaft auf einen anderen Wert alsstatic
oder festgelegt istinitial
). Wenn der direkte Container kein positioniertes Element ist, repräsentiert die Linie nicht den ersten Container in der Hierarchie, sondern ein anderes Element höher in der Hierarchie. Wenn kein positioniertes übergeordnetes Element gefunden wird, verwendet der Browser das Elementhtml
oderbody
als ReferenzHoffe jemand findet es nützlich, nur meine 2 Cent;)
quelle
Wenn Sie scrollWidth verwenden möchten, um die "REAL" CONTENT WIDTH / HEIGHT (da der Inhalt größer sein kann als die CSS-definierte Breite / Höhe-Box) zu erhalten, ist die scrollWidth / Height sehr unzuverlässig, da einige Browser das PaddingRIGHT zu "bewegen" scheinen & paddingBOTTOM, wenn der Inhalt zu groß ist. Dann platzieren sie die Polster rechts / UNTEN des "zu breiten / hohen Inhalts" (siehe Bild unten).
==> Um in einigen Browsern die REAL CONTENT WIDTH zu erhalten, müssen Sie BEIDE Auffüllungen von der Bildlaufbreite abziehen, und in einigen Browsern müssen Sie nur die LEFT Padding abziehen.
Ich habe eine Lösung dafür gefunden und wollte diese als Kommentar hinzufügen, war aber nicht erlaubt. Also habe ich das Bild gemacht und es in Bezug auf die "bewegten Polster" und die "unzuverlässige Scrollbreite" etwas klarer gemacht. Im BLAUEN BEREICH finden Sie meine Lösung, wie Sie die "ECHTE" INHALTSBREITE erhalten!
Hoffe, das hilft, die Dinge noch klarer zu machen!
quelle
Es gibt einen guten Artikel über MDN, der die Theorie hinter diesen Konzepten erklärt: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements
Außerdem werden die wichtigen konzeptionellen Unterschiede zwischen der Breite / Höhe von boundingClientRect und der OffsetWidth / OffsetHeight erläutert.
Um die Theorie richtig oder falsch zu beweisen, benötigen Sie einige Tests. Das habe ich hier gemacht: https://github.com/lingtalfi/dimensions-cheatsheet
Es wird auf Chrome53, ff49, Safari9, Edge13 und IE11 getestet.
Die Ergebnisse der Tests beweisen, dass die Theorie im Allgemeinen richtig ist. Für die Tests habe ich 3 Divs erstellt, die jeweils 10 Lorem-Ipsum-Absätze enthalten. Einige CSS wurde auf sie angewendet:
Und hier sind die Ergebnisse:
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)
Abgesehen von dem Höhenwert von boundingClientRect (299.9999694824219 anstelle von erwarteten 300) in edge13 und ie11 bestätigen die Ergebnisse, dass die dahinter stehende Theorie funktioniert.
Von dort aus ist hier meine Definition dieser Konzepte:
Hinweis: Die Standardbreite der vertikalen Bildlaufleiste beträgt 12px in edge13, 15px in chrome53, ff49 und safari9 und 17px in ie11 (durchgeführt durch Messungen in Photoshop anhand von Screenshots und durch die Testergebnisse bestätigt).
In einigen Fällen verwendet Ihre App jedoch möglicherweise nicht die Standardbreite der vertikalen Bildlaufleiste.
Angesichts der Definitionen dieser Konzepte sollte die Breite der vertikalen Bildlaufleiste also gleich sein (im Pseudocode):
Layoutdimension: offsetWidth - clientWidth - (borderLeftWidth + borderRightWidth)
Rendering-Dimension: boundingClientRect.width - clientWidth - (borderLeftWidth + borderRightWidth)
Hinweis: Wenn Sie Layout und Rendering nicht verstehen, lesen Sie bitte den MDN-Artikel.
Wenn Sie einen anderen Browser haben (oder die Ergebnisse der Tests selbst sehen möchten), können Sie meine Testseite hier sehen: http://codepen.io/lingtalfi/pen/BLdBdL
quelle