StackOverflowには、offsetWidth / clientWidth / scrollWidth(および-Height)に関するいくつかの質問がありますが、それらの値の包括的な説明はありません。
また、Webには、混乱または不正確な情報を提供するソースがいくつかあります。
いくつかの視覚的なヒントを含む完全な説明を提供できますか?また、これらの値を使用してスクロールバーの幅を計算するにはどうすればよいですか?
StackOverflowには、offsetWidth / clientWidth / scrollWidth(および-Height)に関するいくつかの質問がありますが、それらの値の包括的な説明はありません。
また、Webには、混乱または不正確な情報を提供するソースがいくつかあります。
いくつかの視覚的なヒントを含む完全な説明を提供できますか?また、これらの値を使用してスクロールバーの幅を計算するにはどうすればよいですか?
回答:
CSSボックスモデルは、特にコンテンツのスクロールに関しては、かなり複雑です。ブラウザはCSSの値を使用してボックスを描画しますが、CSSしか持っていない場合、JSを使用してすべての寸法を決定することは簡単ではありません。
:それは、各要素があなたの便宜のために6つのDOMプロパティを持っている理由ですoffsetWidth
、offsetHeight
、clientWidth
、clientHeight
、scrollWidth
とscrollHeight
。これらは、現在の視覚的なレイアウトを表す読み取り専用の属性であり、すべて整数です(したがって、丸めエラーが発生する可能性があります)。
詳しく見てみましょう:
offsetWidth
、offsetHeight
:すべての境界線を含むビジュアルボックスのサイズ。要素にwidth
/ height
とパディングおよびボーダーを追加して計算できます。display: block
clientWidth
、clientHeight
:枠線やスクロールバーは含まれませんが、パディングは含まれます。CSSから直接計算することはできません。システムのスクロールバーのサイズによって異なります。scrollWidth
、scrollHeight
:現在スクロール領域の外側に隠れている部分を含む、ボックスのすべてのコンテンツのサイズ。CSSから直接計算できません。コンテンツによって異なります。以来offsetWidth
考慮にスクロールバーの幅を取る、我々は式を経て、スクロールバーの幅を計算するためにそれを使用することができます
scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth
残念ながら、は常に整数であるためoffsetWidth
、丸め誤差が発生clientWidth
する可能性がありますが、実際のサイズは1以外のズームレベルでは小数になる場合があります。
これは
scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth
Chromeは、スクロールバーが既に差し引かれた状態で戻るため、Chromeでは確実に機能しませんwidth
。(また、ChromeはpaddingBottomをスクロールコンテンツの下部にレンダリングしますが、他のブラウザはレンダリングしません)
naturalWidth
とnaturalHeight
scrollHeight
含まれるpadding-bottom
が含まれscrollWidth
ない理由padding-right
clientWidth
以下のためには、document.documentElement.clientWidth
含まれているようだと異なりpadding
、borders
とmargin
一部の人々が、どの名前がどの値に対応するかを覚えておくのに役立つと思われる、より包括的でわかりやすいバージョンを作成しました。私はChrome Dev Toolのカラーコードを使用しました。ラベルは対称的に構成されているため、類推をよりすばやく理解できます。
注1:clientLeft
テキストの方向が右から左に設定されている場合は、垂直スクロールバーの幅も含まれます(その場合、バーは左に表示されるため)。
注2:最も外側の線が最も近い表し位置付け親(その要素position
のプロパティとは異なる値に設定されている
static
か、initial
)を。したがって、直接コンテナが配置された
要素でない場合、線は階層内の最初のコンテナではなく、階層内でより高い別の要素を表します。配置された親が見つからない場合
、ブラウザはhtml
またはbody
要素を参照として使用します
誰かがそれが便利だと思うことを願って、ちょうど私の2セント;)
一部のブラウザはpaddingRIGHTを「移動」しているように見えるため、scrollWidthを使用して「REAL」の CONTENT WIDTH / HEIGHT(コンテンツはcssで定義されたwidth / height-Boxよりも大きくなる可能性があるため)を取得する場合、scrollWidth / Heightは非常に信頼性が低くなります。 &paddingBOTTOM(コンテンツが大きすぎる場合)。次に、「広すぎる/高すぎるコンテンツ」の右/下にパディングを配置します(下の画像を参照)。
==>したがって、一部のブラウザでREAL CONTENT WIDTHを取得するには、スクロール幅から両方のパディングを減算する必要があり、一部のブラウザでは、左のパディングのみ減算する必要があります。
私はこれの解決策を見つけ、これをコメントとして追加したかったのですが、許可されませんでした。だから私は写真を撮り、「移動したパディング」と「信頼できないscrollWidth」に関してそれを少し明確にしました。青い領域では、「実際の」コンテンツの幅を取得する方法に関する私の解決策を見つけます!
これが物事をより明確にするのに役立つことを願っています!
これらの概念の背後にある理論を説明するMDNに関する優れた記事があります。https: //developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_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
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)
したがって、edge13とie11のboundingClientRectの高さの値(予想される300ではなく299.9999694824219)を除いて、この結果は、この背後にある理論が機能することを裏付けています。
そこから、これらの概念の私の定義は次のとおりです。
注:デフォルトの垂直スクロールバーの幅は、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
element.getBoundingClientRect()
(developer.mozilla.org/en-US/docs/Web/API/Element.clientWidthのメモを参照)