JavaScript で HTMLの要素の高さ / 幅を取得しようと思った時、outer やら avail やら offset やら、オブジェクトにやたらとプロパティが生えていて混乱したのでまとめました。
検証環境
iMac / iPad / iPhone にて 2021年10月時点での Google Chrome 最新版で検証しました。デスクトップ版の Chrome は v94 でした。
プロパティを全列挙するとごちゃごちゃして見づらくなるため、高さに絞って説明しています。幅を得る時は Height を Width に読み替えてください。
ディスプレイのサイズ - screen オブジェクト
デバイスのディスプレイのサイズを得るには screen オブジェクト を参照します。
const h1 = window.screen.height;
const h2 = window.screen.availHeight;
height は画面の高さをピクセル数で表します。macOS の Dock を除いた領域は availHeight で得る事ができます。
ブラウザのサイズ - window オブジェクト
ブラウザのサイズを得るには window オブジェクト を参照します。ブラウザが画面いっぱいに広がるタブレット・スマートフォンでは、ビューポートすなわち画面全体のサイズと同じです。
const h1 = window.outerHeight;
const h2 = window.innerHeight;
outerHeight はブラウザの高さそのものです。innerHeight はタブバーやブックマークバーを除いた HTML 文書の表示領域の高さです。
HTML の領域のサイズ - document.documentElement オブジェクト
HTML の領域のサイズを得るには document.documentElement オブジェクト を参照します。このオブジェクトはブラウザではルートの <html>
要素を示します。
const h1 = document.documentElement.offsetHeight;
const h2 = document.documentElement.scrollHeight;
const h3 = document.documentElement.clientHeight;
図の緑色の枠は、文書などのコンテンツがレンダリングされた領域を示しています。
offsetHeight は線やスクロールバーを含む高さを整数で得る事ができます。コンテンツが伸びて縦スクロールが発生する場合は、伸びた分の高さがセットされます。
scrollHeight は線・マージン・スクロールバーを含まない内側のサイズです。コンテンツが伸びて縦スクロールが発生する場合は、伸びた分の高さがセットされます。
clientHeight は線・マージンを含まない内側のサイズです。コンテンツの伸び縮みは影響しません。
コンテンツ領域のサイズ - body オブジェクト
コンテンツ領域のサイズを得るには body オブジェクト を参照します。
左の図は中身のコンテンツに合わせて body が伸び縮みする例を示しています。右の図は height:100vh
など高さを制限した例を示しています。
const h1 = document.body.offsetHeight;
const h2 = document.body.scrollHeight;
const h3 = document.body.clientHeight;
offsetHeight は線やパディングを含む高さを整数で得る事ができます。body の高さそのものを表した値で、中身のコンテンツがはみ出た分は考慮されません。
scrollHeight は線を含まない内側のサイズです。コンテンツが伸びて縦スクロールが発生する場合は、伸びた分の高さがセットされます。
clientHeight は線を含まない内側のサイズです。body の高さそのものを表した値で、中身のコンテンツがはみ出た分は考慮されません。
サンプル
screen / window / document / body の数値を書き出すサンプルページを作ってみました。
手元の実機で試した結果は以下の通りです。
device | screen.height | screen.availHeight | window.outerHeight | window.innerHeight |
---|---|---|---|---|
iMac 27 inch 全画面モード |
1,440 | 1,415 | 1,440 | 1,440 |
iPad Pro 12.9 inch 5th | 1,366 | 1,024 | 1,024 | 649 |
iPhone 7 Plus | 736 | 736 | 736 | 679 |
iMac は解像度と一致しました。
https://support.apple.com/kb/sp689?locale=ja_JP
iPad (横向きに置いています) は @GENZ_INC さんの iPad画面サイズ、ピクセル数早見表 の「CSSピクセル」と一致しました。
iPhone は @tomohisaota さんの iPhone/iPad/Apple Watch解像度(画面サイズ)早見表 の「ポイント」と一致しました。
ブラウザの開発者ツールでデバイスをエミュレートすると、任意のサイズのディスプレイでブラウザを画面いっぱいに広げた扱いになるようです。
要素のサイズ - Element 基底クラス
HTML の要素の基底クラス Element は getBoundingClientRect メソッドを所有しています。このメソッドはビューポートからの位置のジオメトリである DomRect を返します。
const domRect = document.getElementById("foo").getBoundingClientRect();
/* domRect: DomRect
{
x: 65
y: 65
width: 430
height: 430
top: 65
right: 495
bottom: 495
left: 65
}
*/
top は要素の上位置を表します。height は線を含む要素そのものの高さです。bottom は要素の下端の位置を表します。
要素の中のコンテンツのサイズを得るには Element のプロパティを参照します。
const h1 = document.getElementById("foo").offsetHeight;
const h2 = document.getElementById("foo").scrollHeight;
const h3 = document.getElementById("foo").clientHeight;
offsetHeight は線を含む要素そのものの高さを表します。この数値は getBoundingClientRect().height と一致します。
scrollHeight はコンテンツ全体の表示領域の高さを表します。コンテンツが伸びて縦スクロールが発生する場合は、伸びた分の高さも含みます。
clientHeight はコンテンツの表示領域のうち視認できる部分の高さを表します。
まとめ
こうして整理してみるとなかなかに複雑ですね。outer / avail / offset などプロパティのプレフィクスは計算の意味を示したものとなっているようです。どのオブジェクトからどの数値を得るかを掴んでおけば混乱せずに目的の数値にたどり着く事ができそうです。