戦え、エンジニア諸君!!
スマホで100vhが足りない/はみ出す――その地獄はアドレスバーの伸び縮みが犯人だ。
今日こそ 100dvh / 100lvh / 100svh
を手に入れ、高さレイアウトの主導権を取り戻せッ!
Contents
✅ まず結論
- 迷ったら:
100dvh
(Dynamic)…「今この瞬間」の高さに追従してズレを潰す。 - 常に最大高で張りたい:
100lvh
(Large)…URLバーが最も縮んだ状態の高さ。 - 常に最小高で安全に:
100svh
(Small)…URLバーが最も伸びた状態の高さ。
🧠 なぜ「100vh」がズレるのか
モバイルブラウザはスクロールに応じてUI(アドレスバー/ツールバー)を表示・非表示にする。 古典 100vh
は「理論上のビューポート」を基準にするため、UIの出現で実画面の高さと乖離しやすい。 そこで登場したのが“vh三兄弟”だッ!
📏 3 つの新単位を一枚で理解
単位 | 意味 | 使いどころ |
---|---|---|
100dvh | Dynamic:現在の表示領域の高さ | ヒーロー、全画面モーダル、スワイプで高さが変化する画面 |
100lvh | Large:UIが消えた最大の高さ | 「常にピッタリ全画面」を保証したい固定ビュー |
100svh | Small:UIが出た最小の高さ | フォーム入力時(キーボード展開)でも切れたくない安全設計 |
🛠 レシピ集(コピペで即導入)
1) ヒーローセクション(まずはコレ)
.hero {
min-height: 100svh; /* 最小でも収まる */
height: 100dvh; /* ふだんは現在高さに追従 */
max-height: 100lvh; /* 伸びても上限は最大高さまで */
display: grid;
place-items: center;
}
2) 全画面モーダル(スクロール連動で伸縮)
.modal {
position: fixed; inset: 0;
height: 100dvh;
overflow: auto;
background: rgba(0,0,0,.6);
}
3) 入力フォーム画面(キーボードで隠したくない)
.form-page {
min-height: 100svh; /* 一番小さい高さでも破綻しない */
padding-bottom: env(keyboard-inset-height, 0px); /* 一部ブラウザのキーボード領域に備える */
}
4) 「常に最大」で切り替えなしに張りたい
.fixed-view {
height: 100lvh; /* URLバーが消えた最大値を常に採用 */
}
🧯 フォールバック&安全策
古い環境への二段書き(プログレッシブ)
.full {
height: 100vh; /* 旧環境の保険 */
height: 100dvh; /* モダン環境で上書き */
}
@supports で明示分岐
.full {
height: 100vh;
}
@supports (height: 100dvh) {
.full { height: 100dvh; }
}
ノッチ/安全域に備える(iOSの切欠き回避)
.safe {
padding:
calc(env(safe-area-inset-top, 0px) + 16px)
16px
calc(env(safe-area-inset-bottom, 0px) + 16px);
}
🧪 デバッグ奥義
- Chrome DevTools → “Toggle device toolbar”でアドレスバー表示/非表示を切替え、各単位の挙動を確認。
- iOS / Android 実機でスクロール時・キーボード展開時の再現を必ず行う。
min()
/max()
/clamp()
で高さの暴れを制御(例:min(100lvh, 1200px)
)。
📝 使い分けクイックチャート
- とりあえず破綻させたくない:
height:100dvh;
- 常に最大で没入表示:
height:100lvh;
- フォームで切れたくない:
min-height:100svh;
- 旧環境に配慮:
100vh → 100dvh の二段書き
📖 関連書籍・参考資料
フロントエンド実装や最新CSSを体系的に学びたい方には、以下の本がおすすめです。
※ 上記リンクは Amazonアソシエイトリンクを利用しています。
🔥 団長の喝──高さの支配者になれッ!
vh
の呪縛に別れを告げ、dvh / lvh / svhを使い分けろ。 レイアウトは数字を盛る戦いではない、状況を制する戦いだ。
戦え、エンジニア諸君!! ビューポートの波を乗りこなし、 どんな画面でも“ピタッ”と決まる UI を届けよッ!🔥