iOS、Androidのフルページ対応(100dvhとか)

2023年1月現在、端末の画面高さぴったりに表示したい時、CSSだけでiOSAndroid両方対応するのは無理っぽい。JavaScriptも使わないといけないようだ。さもなくばposition: absolute; bottom: 0; 指定した要素がアドレスバーの裏側に回ったりする。

iOSAndroid個別に対応する場合は以下でうまくいくようだ。

iOSの場合

bodyタグ下などルートとなる親要素のstyleを以下のようにする。

.root {
  height: 100vh;
  height: 100dvh;
}

こうすると100dvhに対応していないブラウザは、100dvhの指定は無視され100vhが適用される。100dvhに対応しているブラウザは100vhを100dvhの指定で上書きする。

Androidの場合

100vhではうまくいかない。JavaScriptでwindow.innerHeightをルート要素のheightにセットするのが確実らしい。多分、これでPCブラウザもうまくいくはず。

iOSAndroid両方対応する

以上のことを踏まえて両方対応するなら、以下のようにすればいいはず。

<html>
  <body>
    <div id="root" class="root">        
      <main class="main">
        <!-- メインコンテンツ -->
      </main>
    </div>
  </body>
</html>

<style>
.root {   
  height: 100vh;
  height: 100dvh;

  // 端末下からはみ出た部分はスクロールで見られるようにしたい場合
  overflow: scroll;
}

.main {
   // rootの高さに合わせたい場合
   height: 100%;
}
</style>

<script>
// ブラウザ生JavaScriptではなくES2015とかの記述
window.addEventListener('load', (event) => {
    const isIPhone = () => {
      const ua = navigator.userAgent;
      const regexp = /iPhone.+Mobile/g;
      return regexp.exec(ua) !== null;
    };

    const setFullPageHeight = () => {
      // iPhoneはCSSの指定のままで良い
      if (isIPhone()) return;
      // Android、その他はwindowの高さに合わせる
      document.getElementById("root").style.height = `${window.innerHeight}px`;
    };

    setFullPageHeight();

    // ウィンドウリサイズ時に高さを再設定
    let timeoutId;
    window.addEventListener('resize', () => {
      clearTimeout(timeoutId);
      timeoutId = window.setTimeout(setFullPageHeight, 200);
    });
});
</script>