それぞれ、offsetWidth、clientWidth、scrollWidth、および-Heightについて


385

StackOverflowには、offsetWidth / clientWidth / scrollWidth(および-Height)に関するいくつかの質問がありますが、それらの値の包括的な説明はありません。

また、Webには、混乱または不正確な情報を提供するソースがいくつかあります。

いくつかの視覚的なヒントを含む完全な説明を提供できますか?また、これらの値を使用してスクロールバーの幅を計算するにはどうすればよいですか?

回答:


869

CSSボックスモデルは、特にコンテンツのスクロールに関しては、かなり複雑です。ブラウザはCSSの値を使用してボックスを描画しますが、CSSしか持っていない場合、JSを使用してすべての寸法を決定することは簡単ではありません。

:それは、各要素があなたの便宜のために6つのDOMプロパティを持っている理由ですoffsetWidthoffsetHeightclientWidthclientHeightscrollWidthscrollHeight。これらは、現在の視覚的なレイアウトを表す読み取り専用の属性であり、すべて整数です(したがって、丸めエラーが発生する可能性があります)。

詳しく見てみましょう:

  • offsetWidthoffsetHeight:すべての境界線を含むビジュアルボックスのサイズ。要素にwidth/ heightとパディングおよびボーダーを追加して計算できます。display: block
  • clientWidthclientHeight:枠線やスクロールバーは含まれませんが、パディングは含まれます。CSSから直接計算することはできません。システムのスクロールバーのサイズによって異なります。
  • scrollWidthscrollHeight:現在スクロール領域の外側に隠れている部分を含む、ボックスのすべてのコンテンツのサイズ。CSSから直接計算できません。コンテンツによって異なります。

CSS2ボックスモデル

試してみてください:jsFiddle


以来offsetWidth考慮にスクロールバーの幅を取る、我々は式を経て、スクロールバーの幅を計算するためにそれを使用することができます

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

残念ながら、は常に整数であるためoffsetWidth、丸め誤差が発生clientWidthする可能性がありますが、実際のサイズは1以外のズームレベルでは小数になる場合があります。

これは

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

Chromeは、スクロールバーが既に差し引かれた状態で戻るため、Chromeでは確実に機能しませwidth。(また、ChromeはpaddingBottomをスクロールコンテンツの下部にレンダリングしますが、他のブラウザはレンダリングしません)


27
整数よりも細かい粒度を求める場合は、次を使用しますelement.getBoundingClientRect()developer.mozilla.org/en-US/docs/Web/API/Element.clientWidthのメモを参照)
Anson Kao

1
レイアウトによっては、scrollWidthとscrollHeightが:: beforeと:: afterの疑似要素のサイズを取得するのに非常に役立つことに注意してください。
David

また、それらはに関連しない方法を説明するために有用であろうnaturalWidthnaturalHeight
YakovL

scrollHeight含まれるpadding-bottomが含まれscrollWidthない理由padding-right
JunGor 2017年

clientWidth以下のためには、document.documentElement.clientWidth含まれているようだと異なりpaddingbordersmargin
Drenai

50

一部の人々が、どの名前がどの値に対応するかを覚えておくのに役立つと思われる、より包括的でわかりやすいバージョンを作成しました。私はChrome Dev Toolのカラーコードを使用しました。ラベルは対称的に構成されているため、類推をよりすばやく理解できます。

ここに画像の説明を入力してください

  • 注1:clientLeftテキストの方向が右から左に設定されている場合は、垂直スクロールバーの幅も含まれます(その場合、バーは左に表示されるため)。

  • 注2:最も外側の線が最も近い表し位置付け親(その要素positionのプロパティとは異なる値に設定されている staticか、initial)を。したがって、直接コンテナが配置された 要素でない場合、線は階層内の最初のコンテナではなく、階層内でより高い別の要素を表します。配置された親が見つからない場合 、ブラウザはhtmlまたはbody 要素を参照として使用します


誰かがそれが便利だと思うことを願って、ちょうど私の2セント;)


30

一部のブラウザはpaddingRIGHTを「移動」しているように見えるため、scrollWidthを使用して「REAL」の CONTENT WIDTH / HEIGHT(コンテンツはcssで定義されたwidth / height-Boxよりも大きくなる可能性があるため)を取得する場合、scrollWidth / Heightは非常に信頼性が低くなります。 &paddingBOTTOM(コンテンツが大きすぎる場合)。次に、「広すぎる/高すぎるコンテンツ」の右/下にパディングを配置します(下の画像を参照)。

==>したがって、一部のブラウザでREAL CONTENT WIDTHを取得するには、スクロール幅から両方のパディングを減算する必要があり、一部のブラウザでは、左のパディングのみ減算する必要があります。

私はこれの解決策を見つけ、これをコメントとして追加したかったのですが、許可されませんでした。だから私は写真を撮り、「移動したパディング」と「信頼できないscrollWidth」に関してそれを少し明確にしました。青い領域では、「実際の」コンテンツの幅を取得する方法に関する私の解決策を見つけます!

これが物事をより明確にするのに役立つことを願っています!

ここに画像の説明を入力してください


13

これらの概念の背後にある理論を説明するMDNに関する優れた記事があります。https//developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Det​​ermining_the_dimensions_of_elements

また、boundingClientRectの幅/高さとoffsetWidth / offsetHeightの重要な概念上の違いについても説明します。

次に、理論が正しいか間違っているかを証明するには、いくつかのテストが必要です。それは私がここでやったことです:https//github.com/lingtalfi/dimensions-cheatsheet

chrome53、ff49、safari9、edge13、ie11をテストしています。

テストの結果は、理論が一般的に正しいことを証明しています。テストでは、それぞれ10のlorem ipsum段落を含む3つのdivを作成しました。それらにいくつかのCSSが適用されました:

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

そしてここに結果があります:

  • 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(エッジ13)
    • 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.height: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(エッジ13)
    • scrollWidth:503(ie11)
    • scrollHeight:916(chrome53、safari9)
    • scrollHeight:954(ff49)
    • scrollHeight:922(edge13、ie11)

したがって、edge13とie11のboundingClientRectの高さの値(予想される300ではなく299.9999694824219)を除いて、この結果は、この背後にある理論が機能することを裏付けています。

そこから、これらの概念の私の定義は次のとおりです。

  • offsetWidth / offsetHeight:レイアウト枠ボックスの寸法
  • boundingClientRect:レンダリング境界ボックスの寸法
  • clientWidth / clientHeight:レイアウトパディングボックスの可視部分の寸法(スクロールバーを除く)
  • scrollWidth / scrollHeight:スクロールバーによって制約されていない場合のレイアウトパディングボックスの寸法

注:デフォルトの垂直スクロールバーの幅は、edge13で12px、chrome53、ff49とsafari9で15px、ie11で17pxです(スクリーンショットからのphotoshopでの測定によって行われ、テストの結果によって正しく証明されています)。

ただし、場合によっては、アプリがデフォルトの垂直スクロールバーの幅を使用していないことがあります。

したがって、これらの概念の定義を前提として、垂直スクロールバーの幅は(擬似コードで)に等しくなければなりません。

  • レイアウト寸法:offsetWidth-clientWidth-(borderLeftWidth + borderRightWidth)

  • レンダリングディメンション:boundingClientRect.width-clientWidth-(borderLeftWidth + borderRightWidth)

レイアウトとレンダリングがよくわからない場合は、MDNの記事をご覧ください。

また、別のブラウザーを使用している場合(または自分でテストの結果を確認したい場合)、私のテストページをここで確認できます。http//codepen.io/lingtalfi/pen/BLdBdL

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.