その100 vh、スマホで崩れていませんか?ビューポート問題の歴史と結論

多くの開発者を悩ませた「モバイルブラウザの100 vh問題」とは

モバイルのアドレスバー・ナビゲーションバーが表示/非表示になるたびに 100 vh が実際の画面高とズレ、ヒーローセクションがはみ出したり白帯が出現したりする――これが100 vh問題です。

結論:svh / lvh / dvh の登場で JavaScript はほぼ不要に

CSS Values & Units Lv 4で追加された svh (最小高)・lvh (最大高)・dvh (動的高) が正式仕様化され、主要ブラウザでは 93 %以上のグローバルシェアで対応済み ですCan I Use

この記事を読めば「最適な単位」が自分で選べるようになる

後半で UI パターン別早見表パフォーマンス/アクセシビリティの落とし穴 まで網羅します。


svh / lvh / dvh とは?3つの新しい単位を5分で理解する

単位 意味 使われるタイミング
svh Small Viewport Height:UIが最大表示(バーが出ている)状態での 1 % “とにかく全部見せたい” フォーム、モーダル
lvh Large Viewport Height:UIが最小表示(バーが隠れた)状態での 1 % フルスクリーンの背景画像、動画
dvh Dynamic Viewport Height:UIの出入りに合わせ動的追従 ファーストビュー、全画面セクション

【図解】vh と svh / lvh / dvh の違い

css
/* 従来 */

.hero { height: 100vh; } /* UI 出現ではみ出し */

/* モダン */

.hero { height: 100dvh; } /* UI に合わせ自動可変 */


【実践】UI パターン別・最適なビューポート単位の選び方

UIパターン 推奨単位 理由
ファーストビュー(ヒーロー) 100dvh スクロールでUIが出入りしても常に全画面
画面固定モーダル 100svh UIが最大表示でも内容を欠けさせない
下部固定フッター calc(100svh - footer高さ) UI最大時にもフッターが重ならない
イマーシブ全画面画像 100lvh UIが隠れたときに最大領域を活用

プロなら知っておきたい注意点と応用テクニック

dvh のパフォーマンスは大丈夫?

dvh は UI の出入りごとに再レイアウトが走るため レイアウト計算回数が増加 します。実測では「ヒーロー1枚 + テキスト程度」なら問題はありませんが、パララックスや多段アニメーションと併用すると repaint が増える ので注意が必要ですDEV Community

アクセシビリティへの配慮

  • dvh で高さを固定した要素は 内部スクロール が発生しやすい。max-height:90dvh; overflow:auto; で回避。

  • OS の拡大表示設定時に想定外の折り返しが起きたら、padding を相対値にするなど調整。

vmin / vmax との組み合わせテク

css
.section{

min-height: calc(100dvh - 10vmax); /* 縦横比に応じた余白を自動調整 */

}

ブラウザサポートとフォールバック

主要ブラウザは Chrome 108+ / Safari 15.4+ / Firefox 101+ / Edge 108+ でフルサポート。古い端末向けに次のようなプログレッシブエンハンスを推奨しますDEV Community

css
.container {

height: 100vh; /* まず従来単位 */

}

@supports(height: 100dvh) {

.container { height: 100dvh; } /* 対応ブラウザで上書き */
}


まとめ:ビューポート単位を使いこなし、UI の品質を向上させよう

  • svh / lvh / dvh は 100 vh 問題を根本解決する最新 CSS 単位

  • UI パターン別に適切な単位を選ぶ ことでレイアウト崩れ・白帯を防止

  • パフォーマンスとアクセシビリティ を意識した実装で “動いて終わり” から “体験を守る” へ

これからのモバイルファースト設計では 「dvh を基盤に、svh / lvh でチューニング」 が新常識です。ぜひ自分のプロジェクトで試してみてください。