@ledsun blog

無味の味は佳境に入らざればすなわち知れず

ブラウザでdivが表示されているか判定する

Firs Meaningful Paintの高速化

Webアプリケーションの初期描画をを早くしたいです。 今風に言うとFirst Meaningful Paintの高速化です。

大量のデータを読み込んだ際にすべての情報をレンダリングすると時間がかかります。 最初は、HTMLページの上の表の表示領域内のdivを描画し、下の方、表示領域外にあるdivの描画をスキップしたいです。 スキップした要素はスクロールして表示領域に入った時に描画します。

divを表示する位置を計算するロジックがすでにあります。 計算した表示位置が表示領域内にあるかどうかを判定したいです。

あるdiv要素か表示領域内にあるかどうか判定

ロジックの確認のために、あるdiv要素か表示領域内にあるかどうか判定するCodepenを作りました。 結果は開発コンソールに出力しています。 ブラウザの開発ツールを起動してもらうか、Codepenで開いてConsoleを開いてもらうと、出力が確認できます。

See the Pen 表示されている要素を検出する by shigeru.nakajima (@ledsun) on CodePen.

判定条件

結論は次の判定になりました。 横スクロールは想定していません。

const { top, bottom } = div.getBoundingClientRect();

if (0 <= bottom && top <= clientHeight) {
  ret.push(div.id);
}

clientHeightはdocument.documentElement.clientHeightです。

clientHeightはブラウザの表示している領域です。 非常に似たようなプロパティにwindow.innerHeightがあります。 これはスクロールバーが表示されているときにスクロールバーを含んだ高さを返します。 今回は人間の目に見える領域が取得したかったので、スクロールバーを含まないclientHeightを選択しました。*1

またwindow.visualViewport.heightというプロパティもあります。 これはタブレットまたはスマートフォンで、ピンチアウト、ピンチインして拡大縮小したときに見えている領域が取れるようです。 今回はタブレットスマートフォンは考慮しませんでした。

div側は、getBoundingClientRectを使うと表示領域内でのtop, bottomが取れます。 これとclientHeightを比較すると簡単に判定できます。 div全体でなく、一部が表示領域に入った場合にtrueと判定しています。

参考

*1: window.innerHeight を使っても、誤差の範囲で、ユーザーに見える情報にも性能にも影響は無いと思います。