導入
Web開発において、画面の高さに応じたレイアウト調整は頻出する課題です。特に「ファーストビューを画面いっぱいにしたい」「スクロールに応じて要素を制御したい」といった場面でWindow.innerHeightは必須のAPIです。しかし、モバイルブラウザのUI(アドレスバー等)による「実際の表示領域」と「計算上の高さ」のズレに悩まされた経験はありませんか?本記事では、Window.innerHeightの基礎から、現場で確実に機能する実装手法までを解説します。
基礎知識
Window.innerHeightは、ブラウザの表示領域(ビューポート)の高さをピクセル単位で取得するプロパティです。重要なのは、これが「ツールバーやスクロールバーを含む現在のウィンドウ全体の高さ」を返すという点です。一方で、CSSの単位である「vh」は、ブラウザの仕様によってはアドレスバーの出し入れによって伸縮するため、厳密なサイズ制御をJavaScriptで行う場合には、このAPIやdvh(Dynamic Viewport Height)といったCSSの新単位との使い分けが重要になります。
実装/解決策
実務では、リサイズが発生したタイミングで高さを再計算し、CSS変数に値を注入する手法が最も堅牢です。これにより、CSS側で高さを柔軟に制御できるようになります。また、モバイル端末でのズームやUIの可変に対応するため、resizeイベントだけでなく、orientationchangeイベントへの対応も推奨します。
サンプルプログラム
以下のコードは、画面の現在の高さを計算し、CSS変数としてルート要素に設定する実用的なパターンです。
// windowの高さが変わるたびにCSS変数を更新する関数
const setWindowHeight = () => {
// 現在のwindow.innerHeightを取得
const vh = window.innerHeight;
// documentのルート要素(htmlタグ)にCSS変数をセット
// これにより、CSS側で calc(var(--vh) 1) のように使用可能
document.documentElement.style.setProperty('--vh', `${vh}px`);
};
// 初回実行
setWindowHeight();
// リサイズ時に再計算(デバウンス処理を入れるとよりパフォーマンス向上)
window.addEventListener('resize', setWindowHeight);
// CSS側の使用例:
// .full-screen-element { height: var(--vh); }
応用・注意点
現場で注意すべきは「リサイズイベントの頻度」です。window.resizeは非常に高い頻度で発火するため、そのまま処理を詰め込むとブラウザの負荷が跳ね上がります。必ず「デバウンス(Debounce)」処理を挟み、リサイズ終了後に一度だけ計算するようにしましょう。
また、iOS Safariなどのモバイルブラウザでは、アドレスバーの伸縮によってinnerHeightが頻繁に書き換わります。これを防ぐために、CSSの「dvh(Dynamic Viewport Height)」が利用できる環境であれば、JavaScriptを使わずにCSSだけで完結させるのが現在の最適解です。JavaScriptを使用する場合は、iOSの慣性スクロール中やキーボード表示時などのエッジケースを考慮し、レイアウトがガタつかないか必ず実機で検証してください。