Slide 1

Slide 1 text

ページの可視領域を算出する方法について整理する yamatai12 1

Slide 2

Slide 2 text

自己紹介 yamatai12(Webエンジニア) SNS X(taiyama1212) Qiita(yamatai12) Zenn(yamatai12) 趣味は筋トレ プロフィールです、よろしくお願いします 2

Slide 3

Slide 3 text

今日の結論 「ユーザーが“今見ている高さ”が欲しいなら window.visualViewport.height が最適」 ブラウザズーム(ページ全体を拡大・縮小)に追従する ページのピンチアウト、ピンチインにも追従する モバイルの仮想キーボード表示に追従する 動的ツールバーの高さは含まない  →「ユーザーが実際にコンテンツを見られる領域」に近い 3

Slide 4

Slide 4 text

背景:なぜ可視領域が必要だったか 業務で「ユーザーが今見ている範囲」を知りたい場面があった PC だけでなく、モバイルでも使う前提 ここでぶつかった壁: 「“高さっぽい値”を返す API がいくつもある、 、 どれにしたら良いのだろうか」 4

Slide 5

Slide 5 text

まず用語を軽く整理 視覚的ビューポート ウィンドウ / 画面のうち、実際に表示されている範囲 5

Slide 6

Slide 6 text

動的ツールバー モバイルブラウザ下部の、スクロールで出たり消えたりするバー 6

Slide 7

Slide 7 text

仮想(画面)キーボード モバイルで入力中に出てくるソフトウェアキーボード 7

Slide 8

Slide 8 text

高さに関する主な候補たち 今回比較したのはこの4つ: window.innerHeight window.outerHeight window.visualViewport.height document.documentElement.clientHeight 一見どれも「高さ」だが、 「どの世界の高さか」が微妙に違う。 8

Slide 9

Slide 9 text

比較の軸を決める 何を満たしてほしいか? ズーム(ブラウザの拡大縮小)に追従するか ページのピンチイン/アウトに追従するか 仮想キーボード表示で値が変わるか(モバイル) 動的ツールバーの高さを含むか / 含まないか 今回は 「ユーザーがページ上で“今見ている領域”」 を算出したい、という前提で見ていきます。 9

Slide 10

Slide 10 text

window.innerHeight 今表示されている視覚的ビューポートの高さ 水平スクロールバーがあればその高さを含む ブラウザの拡大縮小には追従する ただし、ページのピンチイン/ピンチアウトには追従しない 仮想キーボードの表示には連動しない(モバイル) 動的ツールバーの高さは含まない モバイルのフォーム入力時に 「キーボードを除いた高さ」を取りたい用途だとズレる。 10

Slide 11

Slide 11 text

window.outerHeight ブラウザウィンドウ全体の高さ サイドバー ウィンドウ操作ボタン 枠・リサイズハンドル などを含む もはや「ユーザーが見ているページ領域」からは遠い 可視領域の算出にはほぼ使わない、という判断。 11

Slide 12

Slide 12 text

document.documentElement.clientHeight 今表示されている視覚的ビューポートの高さ ブラウザの拡大縮小には追従する しかし ページのピンチイン/ピンチアウトには追従しない 仮想キーボード表示にも連動しない(モバイル) スクロールバーの厚みを除いた高さ 動的ツールバーの高さは含む ドキュメントレイアウト寄りの値で、 ブラウザUIの変化までは追いかけてくれない。 12

Slide 13

Slide 13 text

主役:window.visualViewport.height 今表示されている視覚的ビューポートの高さ 拡大縮小(ブラウザズーム)に追従 ページのピンチイン/ピンチアウトにも追従 仮想キーボード表示に連動する(モバイル) 動的ツールバーの高さは含まない(モバイル) つまり: 「ユーザーが実際にコンテンツを見られる領域」 を、その時々の UI 状態に合わせて追従してくれる値 13

Slide 14

Slide 14 text

実際に検証してみた iPhone の Safari / Chrome + Web インスペクタで検証 入力フォームにフォーカスし、 仮想キーボードの表示/非表示を切り替えながらコンソールで確認 14

Slide 15

Slide 15 text

例(数字は参考値) : キーボード表示中: visualViewport.height ≒ 320.5px キーボード非表示: visualViewport.height ≒ 547px 一方で innerHeight / clientHeight はほぼ変化しない 確かに visualViewport.height は仮想キーボード表示に連動していた 15

Slide 16

Slide 16 text

まとめ 1. 「可視領域の高さ」と言っても どの UI まで含めたいかで使うべき API は変わる 2. モバイルまで含めて「ユーザーが今見ている範囲」を 正しく算出したいなら window.visualViewport.height が最適 本スライドの詳細は以下の記事にまとめています https://qiita.com/yamatai12/items/270a9cf924eed0b84db2 16

Slide 17

Slide 17 text

参考 https://ja.javascript.info/size-and-scroll-window https://developer.mozilla.org/ja/docs/Web/API/Window/outerHeight https://www.javadrive.jp/javascript/webpage/index6.html https://web.dev/blog/viewport-units https://zenn.dev/catnose99/scraps/e9b1de4ddf2181 https://developer.mozilla.org/ja/docs/Web/API/Window/innerHeight https://developer.mozilla.org/ja/docs/Web/API/VisualViewport/height https://developer.mozilla.org/ja/docs/Web/API/Element/clientHeight https://qiita.com/unsoluble_sugar/items/2a3d06631a6b8259dc44 https://developer.chrome.com/blog/debugging-chrome-on-ios?hl=ja 17

Slide 18

Slide 18 text

比較表 18

Slide 19

Slide 19 text

Webインスペクタ Webインスペクタを使って検証した。 (実機iPhoneのSafari,Chrome) 19