JavaScript から HTML 要素の横幅と高さを取得する方法はいくつか存在します。しかし、それぞれの方法で取得する寸法が微妙に違います。今回は HTML 要素の寸法を取得する方法を一気にまとめて紹介します。
CSS ボックスモデル
HTML 要素の寸法を扱ううえで CSS ボックスモデルの理解は欠かせません。まずは CSS ボックスモデルの概要を説明します。
たとえば div 要素があったとしましょう。この div 要素が表現する矩形の寸法とはどこを指すでしょうか。div 要素のような HTML 要素にはマージン、パディング、ボーダー、コンテンツが関係しています。横幅はマージンを含む?パティングは含む?ボーダーは含む?さて、どれでしょうか。
CSS ボックスモデルでは、これらの領域をどこまで含むかを明確に示すためにボックスを区別して名前を付けています。内側から順に 4 つのボックスが定義されています。
- コンテントボックス
- パディングボックス
- パディングボックス
- マージンボックス
これらのボックスを図示すると次の通りです。
このように一つの HTML 要素は CSS を使うことで、それぞれのボックスの寸法を指定することができます。以降に HTML 要素の寸法を取得する方法をいくつか説明しますが、一度にすべての寸法をまとめて取得できる方法はありません。それぞれの方法でどの長さが得られるのかに注意してご覧ください。
clientWidth / clientHeight プロパティ
要素オブジェクトの clientWidth
および clientHeight
プロパティは、パディングボックスの幅および高さを返します。ただし、インラインの要素(CSS の display
プロパティが inline
の要素)では 0 を返しますので注意が必要です。
また、clientWidth
および clientHeight
プロパティは整数値を返します。1 未満の小数まで厳密に考慮したい場合は注意してください。
#box {
margin: 20px;
border: 1px solid black;
padding: 10px;
width: 100px;
height: 50px;
}
<div id="box">
<span>Hello</span>
</div>
const div_el = document.getElementById('box1');
console.log(div_el.clientWidth + ' x ' + div_el.clientHeight);
// 120 x 70
const span_el = div_el.querySelector('span');
console.log(span_el.clientWidth + ' x ' + span_el.clientHeight);
// 0 x 0
上記サンプルでは、CSS で width に 100px を指定しています。これは div 要素のコンテントボックスの幅が 100px ということになります。CSS で padding
に 10px を指定しています。したがって、clientWidth
の値は 10 + 100 + 10 = 120 ということになります。
span 要素はデフォルトで CSS の display
プロパティは inline
のため、その clientWidth
と clientHeight
プロパティの値は 0 になります。なお、span 要素であっても、CSS で display
プロパティに block
や inline-block
を指定すると、期待通りにパディングボックスの幅と高さを得られます。
offsetWidth / offsetHeight プロパティ
要素オブジェクトの offsetWidth
および offsetHeight
プロパティは、ボーダーボックスの幅および高さを返します。
また、offsetWidth
および offsetHeight
プロパティは整数値を返します。1 未満の小数まで厳密に考慮したい場合は注意してください。
なお、前述の clientWidth
/ clientHeight
プロパティと異なり、offsetWidth
および offsetHeight
プロパティはインラインの要素(CSS の display
プロパティが inline
の要素)でも期待通りの値を返します。
前述の clientWidth
/ clientHeight
プロパティの JavaScript サンプルを offsetWidth
/ offsetHeight
に置き換えると次のようになります。
const div_el = document.getElementById('box');
console.log(div_el.offsetWidth + ' x ' + div_el.offsetHeight);
// 122 x 72
const span_el = div_el.querySelector('span');
console.log(span_el.offsetWidth + ' x ' + span_el.offsetHeight);
// 39 x 24
getComputedStyle() メソッド
window
オブジェクトの getComputedStyle()
メソッドを使うと、レンダリング結果を表す CSS プロパティ情報をオブジェクトとして取得することができます。getComputedStyle()
メソッドは対象となる HTML 要素のオブジェクトを引数に取ります。
CSS プロパティのうち要素の横幅と高さを表すのは width
と height
プロパティですが、これらの寸法はコンテントボックスの寸法のことを表します。
次の例の CSS と HTML は前述のサンプルと同じです。JavaScript では、getComputedStyle()
メソッドを使って div 要素と span 要素の最終的なスタイル情報を取り出し、width
と height
プロパティの値を出力しています。
#box {
margin: 20px;
border: 1px solid black;
padding: 10px;
width: 100px;
height: 50px;
}
<div id="box">
<span>Hello</span>
</div>
const div_el = document.getElementById('box');
const div_style = window.getComputedStyle(div_el);
console.log(div_style.width + ' x ' + div_style.height);
// 100px x 50px
const span_el = div_el.querySelector('span');
const span_style = window.getComputedStyle(span_el);
console.log(span_style.width + ' x ' + span_style.height);
// auto x auto
CSS では、div 要素には width
を明示的に指定している一方、span 要素には何も指定していません。そのため、getComputedStyle()
メソッドから得られるスタイル情報に含まれる width
と height
の値に違いが生じます。div 要素では 100px
という具体的な寸法が得られた一方で、span 要素では auto
という文字列が得られ、実際の寸法が分かりません。
このように getComputedStyle()
メソッドは HTML 要素の寸法を取得する目的においては万能ではありません。また、寸法が得られたとしても、数値としてではなく単位込みの文字列になりますので注意が必要です。
getBoundingClientRect() メソッド
getBoundingClientRect()
メソッドは、該当の HTML 要素の矩形領域の寸法と位置を含んだオブジェクトを返します。ここでは寸法にフォーカスして説明します。
次の例では、前述のサンプルの CSS と HTML はそのままに、getBoundingClientRect()
メソッドを使って div 要素と span 要素の寸法を取得してコンソールに出力します。
const div_el = document.getElementById('box');
const div_rect = div_el.getBoundingClientRect();
console.log(div_rect.width + ' x ' + div_rect.height);
// 122 x 72
const span_el = div_el.querySelector('span');
const span_rect = span_el.getBoundingClientRect();
console.log(span_rect.width + ' x ' + span_rect.height);
// 38.75 x 24
getBoundingClientRect()
メソッドから DOMRect
オブジェクトが得られますが、このサンプルでは変数 div_rect
と span_rect
が DOMRect
オブジェクトに相当します。DOMRect
オブジェクトの width
と height
プロパティが該当の要素の幅と高さを表し、ピクセルを単位とした数値を返します。
この DOMRect
オブジェクトの width
と height
プロパティが表す寸法は、ボーダーボックスの寸法です。つまり offsetWidth
/ offsetHeight
と同じです。
もう一点注目すべきことがあります。span 要素の幅の値が小数になっています。これまで紹介してきた方法の中で唯一、getBoundingClientRect()
メソッドから得られる DOMRect
は小数まで扱え、最も厳密な情報が得られます。
まとめ
これまで紹介した方法から得られる寸法がどの長さを指しているのかをまとめると次のような図になります(横幅のみ掲載)。
私の場合、たまたまかもしれませんが、パディングもボーダーも 0 にしたケースばかりでしたので、これらの違いを意識する必要がありませんでした。私に限らず、多くのシーンでは違いはあまり気にならないのかもしれませんね。
これも私の場合に限るのかもしれませんが、HTML 要素の寸法が必要な時には、寸法だけでなく位置(left
, top
, x
, y
など)も必要になることが多いため、実際には getBoundingClientRect()
メソッドを使うことが多くを占めます。
この記事を書いて気づいたのですが、マージンボックスの寸法を取得する方法がありませんね。おそらく必要性がないのでしょう。私もどういうシーンでそれが必要なのか思いつきませんが、とても気になります。やるとしたら、ボーダーボックスの寸法を getBoundingClientRect()
メソッドから取得し、マージンを getComputedStyle()
メソッドから取得し、それらを足し合わせるのでしょうか。
今回は以上で終わりです。最後まで読んでくださりありがとうございました。それでは次回の記事までごきげんよう。