532 Stimmen

Verständnis von offsetWidth, clientWidth, scrollWidth und -Height entsprechend

Es gibt mehrere Fragen auf StackOverflow bezüglich offsetWidth / clientWidth / scrollWidth (und -Height entsprechend), aber keine gibt eine umfassende Erklärung darüber, was diese Werte sind.

Außerdem gibt es mehrere Quellen im Web, die verwirrende oder falsche Informationen liefern.

Kannst du eine umfassende Erklärung einschließlich einiger visueller Hinweise geben? Wie können diese Werte verwendet werden, um die Breite der Bildlaufleisten zu berechnen?

1142voto

user123444555621 Punkte 139356

Das CSS-Boxmodell ist ziemlich kompliziert, insbesondere wenn es um scrollbaren Inhalt geht. Während der Browser die Werte aus Ihrem CSS verwendet, um Boxen zu zeichnen, ist es nicht einfach, alle Dimensionen mit JS zu bestimmen, wenn Sie nur das CSS haben.

Deshalb hat jedes Element sechs DOM-Eigenschaften für Ihre Bequemlichkeit: offsetWidth, offsetHeight, clientWidth, clientHeight, scrollWidth und scrollHeight. Diese sind schreibgeschützte Attribute, die das aktuelle visuelle Layout darstellen, und alle von ihnen sind Ganzzahlen (also möglicherweise anfällig für Rundungsfehler).

Lassen Sie uns sie im Detail durchgehen:

  • offsetWidth, offsetHeight: Die Größe der visuellen Box einschließlich aller Rahmen. Kann berechnet werden, indem width/height und Padding und Rahmen addiert werden, wenn das Element display: block hat
  • clientWidth, clientHeight: Der visuelle Teil des Boxinhalts, ohne Rahmen oder Scrollleisten, aber inklusive Padding. Kann nicht direkt aus dem CSS berechnet werden, abhängig von der Größe der System-Scrollleiste.
  • scrollWidth, scrollHeight: Die Größe des gesamten Inhalts der Box, einschließlich der Teile, die derzeit außerhalb des Scrollbereichs versteckt sind. Kann nicht direkt aus dem CSS berechnet werden, abhängig vom Inhalt.

CSS2 Box Model

Probieren Sie es aus: jsFiddle


Da offsetWidth die Breite der Scrollleiste berücksichtigt, können wir sie verwenden, um die Breite der Scrollleiste mit der Formel zu berechnen

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

Leider können Rundungsfehler auftreten, da offsetWidth und clientWidth immer Ganzzahlen sind, während die tatsächlichen Größen bei Zoomstufen außer 1 möglicherweise Brüche sind.

Beachten Sie, dass dies

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

nicht zuverlässig in Chrome funktioniert, da Chrome die Breite bereits mit abgezogener Scrollleiste zurückgibt. (Außerdem rendert Chrome paddingBottom unter den Scrollinhalt, während andere Browser dies nicht tun)

97voto

Lual Punkte 2878

Ich habe eine umfassendere und sauberere Version erstellt, die einige Leute nützlich finden könnten, um sich daran zu erinnern, welcher Name welchem Wert entspricht. Ich habe die Farbcodierung von Chrome Dev Tool verwendet und die Labels sind symmetrisch angeordnet, um Analogien schneller zu erkennen:

Bildbeschreibung hier eingeben

  • Hinweis 1: clientLeft enthält auch die Breite der vertikalen Bildlaufleiste, wenn die Textrichtung von rechts nach links eingestellt ist (da die Leiste in diesem Fall links angezeigt wird)

  • Hinweis 2: Die äußerste Linie stellt den nächstgelegenen positionierten Elternteil dar (ein Element, dessen position-Eigenschaft auf einen Wert eingestellt ist, der sich von static oder initial unterscheidet). Wenn also der direkte Container kein positioniertes Element ist, stellt die Linie nicht den ersten Container in der Hierarchie dar, sondern ein anderes Element höher in der Hierarchie. Wenn kein positionierter Elternteil gefunden wird, wird der Browser das html- oder body-Element als Referenz verwenden


Hoffentlich findet jemand es nützlich, nur meine 2 Cent ;)

37voto

Manny_user3297459 Punkte 519

Wenn Sie die scrollWidth verwenden möchten, um die "ECHTE" INHALTSBREITE/-HÖHE (da der Inhalt GRÖSSER sein kann als die vom CSS definierte Breite/Höhe-Box) zu erhalten, ist die scrollWidth/Höhe sehr UNZUVERLÄSSIG, da einige Browser anscheinend das paddingRIGHT und paddingBOTTOM "VERSCHIEBEN", wenn der Inhalt zu groß ist. Sie setzen dann die Paddings am RECHTS/UNTEN des "zu breiten/hohen Inhalts" (siehe Bild unten).

\==> Daher müssen Sie in einigen Browsern, um die ECHTE INHALTSBREITE zu erhalten, BEIDE Paddings von der scrollwidth abziehen, und in einigen Browsern müssen Sie nur das LINKE Padding abziehen.

Ich habe eine Lösung dafür gefunden und wollte dies als Kommentar hinzufügen, was jedoch nicht erlaubt war. Also habe ich das Bild genommen und es ein wenig klarer gemacht in Bezug auf die "verschobenen Paddings" und die "unzuverlässige scrollWidth". In dem BLAUEN BEREICH finden Sie meine Lösung, wie man die "ECHTE" INHALTSBREITE erhält!

Hoffe, das hilft, um die Dinge noch klarer zu machen!

Bildbeschreibung eingeben

19voto

ling Punkte 8381

Es gibt einen guten Artikel auf 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

Es erklärt auch die wichtigen konzeptionellen Unterschiede zwischen boundingClientRect Breite/Höhe vs offsetBreite/offsetHöhe.

Dann, um die Theorie zu beweisen oder widerlegen, benötigen Sie einige Tests. Das ist, was ich hier gemacht habe: https://github.com/lingtalfi/dimensions-cheatsheet

Es testet für chrome53, ff49, safari9, edge13 und ie11.

Die Ergebnisse der Tests bestätigen, 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 wurden auf sie angewendet:

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

Und hier sind die Ergebnisse:

  • div1

    • offsetBreite: 530 (chrome53, ff49, safari9, edge13, ie11)

    • offsetHöhe: 330 (chrome53, ff49, safari9, edge13, ie11)

    • bcr.Breite: 530 (chrome53, ff49, safari9, edge13, ie11)

    • bcr.Höhe: 330 (chrome53, ff49, safari9, edge13, ie11)

    • clientBreite: 505 (chrome53, ff49, safari9)

    • clientBreite: 508 (edge13)

    • clientBreite: 503 (ie11)

    • clientHöhe: 320 (chrome53, ff49, safari9, edge13, ie11)

    • scrollBreite: 505 (chrome53, safari9, ff49)

    • scrollBreite: 508 (edge13)

    • scrollBreite: 503 (ie11)

    • scrollHöhe: 916 (chrome53, safari9)

    • scrollHöhe: 954 (ff49)

    • scrollHöhe: 922 (edge13, ie11)

  • div2

    • offsetBreite: 500 (chrome53, ff49, safari9, edge13, ie11)

    • offsetHöhe: 300 (chrome53, ff49, safari9, edge13, ie11)

    • bcr.Breite: 500 (chrome53, ff49, safari9, edge13, ie11)

    • bcr.Höhe: 300 (chrome53, ff49, safari9)

    • bcr.Höhe: 299.9999694824219 (edge13, ie11)

    • clientBreite: 475 (chrome53, ff49, safari9)

    • clientBreite: 478 (edge13)

    • clientBreite: 473 (ie11)

    • clientHöhe: 290 (chrome53, ff49, safari9, edge13, ie11)

    • scrollBreite: 475 (chrome53, safari9, ff49)

    • scrollBreite: 478 (edge13)

    • scrollBreite: 473 (ie11)

    • scrollHöhe: 916 (chrome53, safari9)

    • scrollHöhe: 954 (ff49)

    • scrollHöhe: 922 (edge13, ie11)

  • div3

    • offsetBreite: 530 (chrome53, ff49, safari9, edge13, ie11)

    • offsetHöhe: 330 (chrome53, ff49, safari9, edge13, ie11)

    • bcr.Breite: 265 (chrome53, ff49, safari9, edge13, ie11)

    • bcr.Höhe: 165 (chrome53, ff49, safari9, edge13, ie11)

    • clientBreite: 505 (chrome53, ff49, safari9)

    • clientBreite: 508 (edge13)

    • clientBreite: 503 (ie11)

    • clientHöhe: 320 (chrome53, ff49, safari9, edge13, ie11)

    • scrollBreite: 505 (chrome53, safari9, ff49)

    • scrollBreite: 508 (edge13)

    • scrollBreite: 503 (ie11)

    • scrollHöhe: 916 (chrome53, safari9)

    • scrollHöhe: 954 (ff49)

    • scrollHöhe: 922 (edge13, ie11)

Also, abgesehen von dem boundingClientRect Höhenwert (299.9999694824219 anstelle der erwarteten 300) in edge13 und ie11, bestätigen die Ergebnisse, dass die Theorie dahinter funktioniert.

Von dort aus hier ist meine Definition dieser Konzepte:

  • offsetBreite/offsetHöhe: Abmessungen des Layout-Border-Box
  • boundingClientRect: Abmessungen der Rendering-Border-Box
  • clientBreite/clientHöhe: Abmessungen des sichtbaren Teils des Layout-Padding-Box (ohne Scrollleisten)
  • scrollBreite/scrollHöhe: Abmessungen der Layout-Padding-Box, wenn sie nicht durch Scrollleisten eingeschränkt wäre

Hinweis: Die Standard-Breite der vertikalen Scrollleiste beträgt 12px in edge13, 15px in chrome53, ff49 und safari9, und 17px in ie11 (gemessen in Photoshop aus Screenshots und durch die Ergebnisse der Tests bestätigt).

In einigen Fällen verwendet Ihre App jedoch möglicherweise nicht die Standard-Breite der vertikalen Scrollleiste.

Also, basierend auf den Definitionen dieser Konzepte sollte die Breite der vertikalen Scrollleiste gleich sein wie (im Pseudocode):

  • Layout Dimension: offsetBreite - clientBreite - (borderLeftBreite + borderRightBreite)

  • Rendering Dimension: boundingClientRect.Breite - clientBreite - (borderLeftBreite + borderRightBreite)

Hinweis: Wenn Sie nicht verstehen, Layout vs. Rendering, lesen Sie bitte den MDN-Artikel.

Außerdem, 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

15voto

abernier Punkte 25010

Meine persönliche Spickzettel, der folgendes abdeckt:

DOM-Elementabmessungen

  • .offsetWidth/.offsetHeight
  • .clientWidth/.clientHeight
  • .scrollWidth/.scrollHeight
  • .scrollLeft/.scrollTop
  • .getBoundingClientRect()

mit kleinen/einfachen/nicht alles in einem Diagrammen :)


siehe in voller Größe: https://docs.google.com/drawings/d/1bOOJnkN5G_lBs3Oz9NfQQH1I0aCrX5EZYPY3mu3_ROI/edit?usp=sharing

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X