👌

100vhの罠を回避!動的ビューポートにより崩れるレイアウトを回避する3つの方法

に公開

はじめに

スマホ向けwebsiteで高さを100vhに指定すると、アドレスバーの表示/非表示によってビューポートが動的に変化し、意図しないオーバーフローが起きます。
本記事では、その原因と対策をまとめます。

結論だけ知りたい方向け

先に結論です。最新のブラウザでは、svhdvhのサポートが進んでおり、100vhの代わりにこれらを活用することでほとんどのオーバーフロー問題は解決可能です。

各ブラウザの対応状況は 下記を参照してください。
https://caniuse.com/viewport-unit-variants

オーバーフローが起きる原因

そもそもオーバーフローが起きる原因は何でしょうか?

→それはビューポートの高さの変化によるものです。

CSSの100vhはレイアウトビューポートを基準に計算されます。これはアドレスバー非表示時の高さで固定してしまうため、アドレスバーが表示されても、その高さを維持して、後ろに隠れる形でオーバーフローが起きてしまいます。
ここをアドレスバーが表示された場合ユーザーが見える範囲はその分減るので、heightの値もその分小さくしたいです。これが解決の方針となります。

代表的な解決パターン

1. dvh/svhを使う

メリット

CSSだけで実装可能で楽

デメリット

一部のブラウザでは未対応
dvhはビューポイント変化時に高さを再計算するためチラつきが起きる場合がある。

コード

.height {  
    height: 100svh;
}
.height {  
  height: 100dvh;
}  

2. JavaScript/CSS変数を組み合わせた動的制御

メリット

dvhを擬似的にJavaScriptを用いて再現できる

デメリット

JavaScriptの実装が必要となる

(The trick to viewport units on mobile - CSS-Tricks)

コード

:root {  
  --vh: 1vh;  
}  
.height {  
  height: calc(var(--vh) * 100);  
}  

function updateVh() {  
  document.documentElement.style.setProperty(  
    '--vh',  
    `${window.innerHeight * 0.01}px`  
  );  
}  
window.addEventListener('resize', updateVh);  
updateVh(); 

3. スクロール1pxトリック

メリット

簡易的でコードも短い。

デメリット

UX に影響が出る場合があるかも。
ios safariに限定されている。(デバイス依存の挙動差やセキュリティ的制限もありAndroidでは動作しない報告が多数見受けられます。)
https://stackoverflow.com/questions/37395561/how-to-hide-a-mobile-browsers-address-bar
https://stackoverflow.com/questions/78832265/hiding-the-address-bar-on-mobile-when-scrolling-down-within-a-full-page-iframe
https://stackoverflow.com/questions/44462497/hide-address-bar-in-android-chrome-automatically
https://stackoverflow.com/questions/17791705/hide-mobile-browser-address-bar-on-chrome-android
https://support.google.com/chrome/thread/172465478/chrome-for-android-address-bar-not-hiding-when-scrolling

コード

<script>
  // ロード時にアドレスバーを折りたたむ  
  window.scrollBy(0, 1);
</script>  

まとめ

  1. svh/dvhを利用
    2. まずはブラウザ対応状況を確認し、対応が十分であれば svh/dvh を優先的に採用しましょう!
  2. JavaScript と CSS変数を組み合わせた方法
    4. 古いブラウザ対応が必要な場合は、JavaScript と CSS変数を組み合わせた方法が確実です。
  3. スクロールトリック
    6. 最終手段として スクロールトリックを組み合わせると、ほとんどのケースで高さ崩れを防げるでしょう

上記の3つの方法を組み合わせて、モバイルブラウザのアドレスバーによるオーバーフロー問題を解消しましょう!

参考

https://css-tricks.com/the-trick-to-viewport-units-on-mobile/?utm_source=chatgpt.com
https://developer.mozilla.org/en-US/docs/Web/CSS/length
https://developer.mozilla.org/en-US/docs/Web/CSS/CSSOM_view/Viewport_concepts

GAOGAO Engineer Blog

Discussion