要素の幅、高さ、その他の幾何学的特徴に関する情報を読み取るための多くのJavaScriptプロパティがあります。
JavaScriptで要素を移動したり配置したりするときによく必要になります。
サンプル要素
プロパティを実証するためのサンプル要素として、以下に示すものを使用します。
<div id="example">
...Text...
</div>
<style>
#example {
width: 300px;
height: 200px;
border: 25px solid #E8C48F;
padding: 20px;
overflow: auto;
}
</style>
ボーダー、パディング、およびスクロールがあります。全機能セットです。マージンは要素自体の一部ではないため、マージンはなく、マージン用の特別なプロパティもありません。
要素は次のようになります。
サンドボックスでドキュメントを開くことができます。
上の図は、要素にスクロールバーがある場合の最も複雑なケースを示しています。一部のブラウザ(すべてではない)は、コンテンツ(上の「コンテンツ幅」とラベル付けされている)から取得して、スクロールバーのスペースを予約します。
したがって、スクロールバーがない場合、コンテンツ幅は300px
になりますが、スクロールバーが16px
幅(幅はデバイスやブラウザによって異なる場合があります)の場合、300 - 16 = 284px
のみが残り、それを考慮する必要があります。それが、この章の例でスクロールバーがあることを前提としている理由です。スクロールバーがない場合、一部の計算は簡単です。
padding-bottom
領域はテキストで埋められる場合があります通常、パディングは図では空で表示されますが、要素に多くのテキストがあり、オーバーフローする場合は、ブラウザはpadding-bottom
に「オーバーフロー」テキストを表示します。これは正常です。
幾何学
幾何学プロパティを含む全体像を次に示します。
これらのプロパティの値は技術的には数値ですが、これらの数値は「ピクセル単位」であるため、ピクセル測定値です。
要素の外側から始めて、プロパティを調べていきましょう。
offsetParent、offsetLeft/Top
これらのプロパティはめったに必要ありませんが、それでも「最も外側の」幾何学プロパティであるため、それらから始めます。
offsetParent
は、ブラウザがレンダリング中に座標を計算するために使用する最も近い祖先です。
これは、次のいずれかに該当する最も近い祖先です。
- CSSで配置されたもの(
position
はabsolute
、relative
、fixed
、またはsticky
)、または <td>
、<th>
、または<table>
、または<body>
.
プロパティoffsetLeft/offsetTop
は、offsetParent
の左上隅を基準としたx/y座標を提供します。
以下の例では、内側の<div>
にはoffsetParent
として<main>
があり、offsetLeft/offsetTop
が左上隅(180
)からシフトしています。
<main style="position: relative" id="main">
<article>
<div id="example" style="position: absolute; left: 180px; top: 180px">...</div>
</article>
</main>
<script>
alert(example.offsetParent.id); // main
alert(example.offsetLeft); // 180 (note: a number, not a string "180px")
alert(example.offsetTop); // 180
</script>
offsetParent
がnull
になるいくつかのケースがあります。
- 表示されない要素(
display:none
またはドキュメント内にない)。 <body>
および<html>
の場合。position:fixed
の要素の場合。
offsetWidth/Height
次に、要素自体に進みましょう。
これらの2つのプロパティは最も単純なものです。これらは、要素の「外側」の幅/高さを提供します。言い換えれば、ボーダーを含むフルサイズです。
サンプル要素の場合
offsetWidth = 390
– 外側の幅。内側のCSS幅(300px
)にパディング(2 * 20px
)とボーダー(2 * 25px
)を加えたものとして計算できます。offsetHeight = 290
– 外側の高さ。
幾何学プロパティは、表示された要素に対してのみ計算されます。
要素(またはその祖先のいずれか)にdisplay:none
がある場合、またはドキュメント内にない場合、すべての幾何学プロパティはゼロになります(またはoffsetParent
の場合はnull
)。
たとえば、要素を作成したが、まだドキュメントに挿入していない場合、または要素(またはその祖先)にdisplay:none
がある場合、offsetParent
はnull
になり、offsetWidth
、offsetHeight
は0
になります。
これを使用して、要素が非表示になっているかどうかを次のように確認できます。
function isHidden(elem) {
return !elem.offsetWidth && !elem.offsetHeight;
}
このようなisHidden
は、画面上にあり、サイズがゼロの要素に対してtrue
を返すことに注意してください。
clientTop/Left
要素の内部にはボーダーがあります。
それらを測定するために、プロパティclientTop
とclientLeft
があります。
この例では
clientLeft = 25
– 左ボーダーの幅clientTop = 25
– 上ボーダーの幅
...ただし、正確に言うと、これらのプロパティはボーダーの幅/高さではなく、外側から見た内側の相対座標です。
違いは何ですか?
ドキュメントが右から左の場合(オペレーティングシステムがアラビア語またはヘブライ語の場合)に表示されます。スクロールバーは右側ではなく左側にあり、clientLeft
にはスクロールバーの幅も含まれます。
その場合、clientLeft
は25
ではなく、スクロールバーの幅25 + 16 = 41
になります。
ヘブライ語での例を次に示します
clientWidth/Height
これらのプロパティは、要素のボーダーの内側の領域のサイズを提供します。
これらには、スクロールバーなしでコンテンツ幅とパディングが含まれます。
上の図では、まずclientHeight
を考えてみましょう。
水平スクロールバーはないため、ボーダーの内側の合計に完全に一致します。CSSの高さ200px
に上下のパディング(2 * 20px
)を加えた合計240px
です。
次に、clientWidth
です。コンテンツ幅は300px
ではなく284px
です。これは、16px
がスクロールバーによって占有されているためです。したがって、合計は284px
に左右のパディングを加えた合計324px
です。
パディングがない場合、clientWidth/Height
は、ボーダーとスクロールバー(ある場合)の内側のコンテンツ領域に正確に一致します。
したがって、パディングがない場合、clientWidth/clientHeight
を使用してコンテンツ領域のサイズを取得できます。
scrollWidth/Height
これらのプロパティはclientWidth/clientHeight
に似ていますが、スクロールアウト(非表示)部分も含まれています
上の図では
scrollHeight = 723
– スクロールアウト部分を含む、コンテンツ領域の完全な内側の高さです。scrollWidth = 324
– 完全な内側の幅です。ここでは水平スクロールがないため、clientWidth
と同じです。
これらのプロパティを使用して、要素をその全幅/高さに拡張できます。
このように
// expand the element to the full content height
element.style.height = `${element.scrollHeight}px`;
ボタンをクリックして要素を拡張します
scrollLeft/scrollTop
プロパティscrollLeft/scrollTop
は、要素の非表示のスクロールアウト部分の幅/高さです。
下の図では、垂直スクロールのあるブロックのscrollHeight
とscrollTop
を確認できます。
言い換えれば、scrollTop
は「どれだけ上にスクロールされたか」です。
scrollLeft/scrollTop
は変更可能ここにあるほとんどの幾何学プロパティは読み取り専用ですが、scrollLeft/scrollTop
は変更でき、ブラウザは要素をスクロールします。
下の要素をクリックすると、コードelem.scrollTop += 10
が実行されます。これにより、要素のコンテンツが10px
下にスクロールされます。
私
1
2
3
4
5
6
7
8
9
scrollTop
を0
または1e9
のような大きな値に設定すると、要素がそれぞれ一番上/一番下までスクロールされます。
CSSから幅/高さを取得しないでください
DOM要素の幾何学プロパティについて説明しました。これを使用して、幅、高さ、距離を計算できます。
しかし、スタイルとクラスの章で知っているように、getComputedStyle
を使用してCSSの高さと幅を読み取ることができます。
では、次のように、getComputedStyle
で要素の幅を読み取らないのはなぜですか?
let elem = document.body;
alert( getComputedStyle(elem).width ); // show CSS width for elem
代わりに幾何学プロパティを使用する必要があるのはなぜですか?理由は2つあります
-
まず、CSSの
width/height
は別のプロパティbox-sizing
に依存しています。これは、CSSの幅と高さが「何であるか」を定義します。CSSの目的でのbox-sizing
の変更により、このようなJavaScriptが壊れる可能性があります。 -
次に、CSSの
width/height
は、たとえばインライン要素の場合、auto
になる可能性があります。<span id="elem">Hello!</span> <script> alert( getComputedStyle(elem).width ); // auto </script>
CSSの観点から見ると、
width:auto
は完全に正常ですが、JavaScriptでは、計算で使用できるpx
単位の正確なサイズが必要です。したがって、ここでCSSの幅は役に立ちません。
さらに、もう1つ理由があります。スクロールバーです。スクロールバーなしでは正常に機能するコードが、スクロールバーがあるとバグになる場合があります。これは、一部のブラウザではスクロールバーがコンテンツからスペースを占有するためです。したがって、コンテンツで使用できる実際の幅は、CSS幅よりも小さくなります。また、clientWidth/clientHeight
はそれを考慮に入れています。
...しかし、getComputedStyle(elem).width
を使用すると、状況は異なります。一部のブラウザ(例:Chrome)は、スクロールバーを引いた実際の内部幅を返し、一部のブラウザ(例:Firefox)は、CSSの幅(スクロールバーを無視)を返します。このようなクロスブラウザの違いが、getComputedStyle
を使用せず、幾何学プロパティに頼る理由です。
もしブラウザがスクロールバーのための領域を確保する場合(Windowsのほとんどのブラウザがそうです)、以下でテストできます。
テキストを持つ要素は、CSSでwidth:300px
が指定されています。
デスクトップのWindows OSでは、Firefox、Chrome、Edgeのすべてがスクロールバーのために領域を確保します。しかし、Firefoxは300px
と表示する一方で、ChromeとEdgeはそれよりも小さい値を表示します。これは、FirefoxがCSSの幅を返すのに対し、他のブラウザは「実際の」幅を返すためです。
この違いは、JavaScriptからgetComputedStyle(...).width
を読み取る場合にのみ発生することに注意してください。見た目ではすべて正常です。
まとめ
要素は以下の幾何学的プロパティを持ちます。
offsetParent
– 最も近い位置指定された祖先要素、またはtd
、th
、table
、body
です。offsetLeft/offsetTop
–offsetParent
の左上端からの相対座標です。offsetWidth/offsetHeight
– ボーダーを含む要素の「外側」の幅/高さです。clientLeft/clientTop
– 左上外側の角から左上内側(コンテンツ+パディング)の角までの距離です。左から右のOSの場合、常に左/上のボーダーの幅です。右から左のOSの場合、垂直スクロールバーが左側にあるため、clientLeft
にはその幅も含まれます。clientWidth/clientHeight
– スクロールバーを含まない、パディングを含むコンテンツの幅/高さです。scrollWidth/scrollHeight
–clientWidth/clientHeight
と同様にコンテンツの幅/高さですが、スクロールアウトされた、見えない部分も含みます。scrollLeft/scrollTop
– 要素の左上角から始まる、スクロールアウトされた上部の幅/高さです。
すべてのプロパティは読み取り専用ですが、scrollLeft/scrollTop
は変更されるとブラウザが要素をスクロールさせます。
コメント
<code>
タグを使用し、複数行の場合は<pre>
タグで囲み、10行を超える場合はサンドボックスを使用してください (plnkr, jsbin, codepen…)。