2026.09.23 泊まれる場所4,223 立ち寄りスポット59,693 営業中を確認したキャンプ場1,005 note を読む

100vhでスマホの下が切れる原因|アドレスバーの出し引きで「100%」の中身が変わる

トップページの写真をheight:100vhで画面いっぱいにすると、スマホでだけ下が切れて見えることがある。
アドレスバーの出し引きで、100vhの「100%」の中身がそもそも違っているのが原因だ。

トップページの一枚目に写真を画面いっぱいに出したくて、height: 100vh を書く。
パソコンで見るぶんには狙いどおりで、写真の下端がちょうど画面の下端に合う。
ところがスマホで開くと、様子が違うことがある。

写真の下、数十ピクセルぶんだけ次のセクションの白地が見えている。
指で軽くスクロールすると写真は画面いっぱいに収まるのに、ページを開いた直後だけ下が切れて見える。
条件によって見え方が変わるので、最初はキャッシュのせいかと疑いやすい。

こういうときは、ブラウザのせいにする前に自分のCSSを疑うのが基本だ。
ただ、数値に間違いがなくてパソコンでは正しく表示されるなら、手がかりは「スマホでだけ起きる」という点になる。

100vhの「100%」は、状況によって数字が違う

vh は viewport height の略で、画面の高さの1%を表す単位だ。
スマホの場合、その「画面の高さ」の中に、アドレスバーやタブバーといったブラウザ自身のUIが含まれるかどうかで数字が変わる。

ページを開いた直後は、上にアドレスバー、下にツールバーが表示された状態が初期値になっていることが多い。
その状態から下にスクロールすると、ブラウザが「読むのを邪魔しない」と判断してアドレスバーを画面外へ隠す。
隠れた分だけ、実際に見えている領域は広がる。

ここで問題になるのが、100vh がどちらの状態を基準に計算されているかだ。
ブラウザによっては、アドレスバーが隠れた「いちばん広い状態」を基準に100vhを固定している。
ページを開いた直後、アドレスバーがまだ表示されている狭い状態では、100vh分の高さが画面からはみ出す。
はみ出した分だけ、写真の下が見えなくなる。

直すために増えた単位

この不一致はCSSの仕様を決めている団体(W3CのCSS Working Group)でも問題として扱われ、新しい単位が追加された。

svh(small viewport height)は、アドレスバーが出ている「いちばん狭い状態」を基準にする単位。
lvh(large viewport height)は逆に、アドレスバーが隠れた「いちばん広い状態」を基準にする単位。
そして dvh(dynamic viewport height)は、アドレスバーの出し引きに合わせてその場で数字が変わる単位だ。

画面いっぱいの写真には dvh がいちばん合うと思う。
ページを開いた瞬間の狭い状態でも、スクロール後の広い状態でも、そのときの実際の表示領域に合わせて高さが決まる。
アドレスバーが隠れた瞬間、写真の高さもふわっと追従して伸びる。

書き換えは1行、でも順番が要る

該当のCSSは、こう書き換える。

height: 100vh;
height: 100dvh;

同じプロパティを2回書くのは無駄に見えるけれど、これには理由がある。
dvh をまだ知らない古いブラウザは、知らない単位の行をそのまま読み飛ばす仕様になっている。
先に書いた 100vh が生きたまま残るので、古い環境でも最低限の高さは確保される。
新しい環境では後から書いた 100dvh が上書きして効く。
新旧どちらの見え方も切り捨てずに済む、費用対効果のいい直し方だ。

数値をいじって力業で調整するより、単位を変えるほうが早い。
スマホのブラウザは癖が強いと片付けがちだけど、癖ではなく仕様の解釈違いだと思う。
画面いっぱいに何かを表示したいときは、最初から vh ではなく dvh を書くのが無難だ。

まる子パパ

まる子パパ

会社員。受託開発のエンジニアを15年以上続けていて、その前は寿司職人・長距離運転手・農業。 技術ブログは、キャンプの合間に踏んだバグと、AI・Web開発の運用の失敗を書いています。 このサイト自体が、開発に携わっているCMS「コンテナ」の稼働中の実例です。 このサイトについて / 小さな自動化の相談

—

ほかにも書いています

受託・note・スタンプ

※受託の相談とnoteは、運営者が個人で受けている・書いているものです。

技術ブログ一覧へ戻る