Insights

技術情報

Safariの100vh問題は「解決」していない。ただし、選択肢は増えた

iOS Safari における 100vh 問題は、長いあいだフロントエンド開発者を悩ませてきました。最近はあまり話題に上がらなくなったこともあり、「もう解決したのでは?」と思われがちですが、実際には問題そのものが解決したわけではなく、回避手段が増えた状態です。

実際に開発中のサイトで検証した結果をもとに、以下の点を整理します。

  • svh / dvh / lvh それぞれの違い
  • なぜ今回は 100dvh を使わなかったのか
  • 将来また dvh を使うとしたら、どんな条件か

なぜ iOS Safari の 100vh は信用しづらいのか

従来の vh は、レイアウトビューポートを基準に高さが計算されます。

ところが iOS Safari には、以下の特徴があります。

  • アドレスバーが表示されている状態がある
  • スクロールするとアドレスバーが隠れる挙動がある

その結果、次のような現象が起きやすくなります。

  • 初期表示(アドレスバー表示時)では、100vh の要素が可視領域より大きくなり、下部が画面外に隠れる
  • スクロールしてアドレスバーが隠れると見え方が変わり、レイアウトのズレや余白が生じる

これが、いわゆる「Safariの100vh問題」です。


新しい viewport 単位の登場

この問題に対応するため、CSSには以下の viewport 単位が追加されました。それぞれ性質が異なるため、用途に応じた使い分けが求められます。

  • svh(Small Viewport Height)
  • dvh(Dynamic Viewport Height)
  • lvh(Large Viewport Height)

svh / dvh / lvh の違い

単位基準となる高さスクロール時の変化特徴向いている用途
vh従来のビューポート変化しない互換性は高いが誤差が出やすいfallback用途
svh最小のビューポート変化しない安定するメインビジュアル、ヒーロー領域
dvh現在のビューポート変化する見た目は自然アプリ風UI、可変レイアウト
lvh最大のビューポート変化しない高さが最も大きい常時フル表示したい要素

dvh は今見えている領域に合わせて動くのが特徴ですが、スクロールに応じて値が変わる点には注意が必要です。


今回試したコード

height: 100vh;
height: 100svh; /* iOS Safari対策 */
height: 100dvh; /* iOS Safari対策 */
min-height: 600px;

この構成は、vh を fallback として残しつつ、対応ブラウザでは svh / dvh で上書きする意図で記述しています。


なぜ 100dvh を使わなかったのか

メインビジュアルに上記の指定を入れて検証したところ、以下の挙動が確認できました。

  • アドレスバーが消えた瞬間にメインビジュアルの高さが再計算される
  • 画面が動くように見える

見た目としては自然ですが、ファーストビューでレイアウトが動くのはUXとしてあまり好ましくありません。そのため今回は dvh を外し、以下の指定にとどめました。

height: 100vh;
height: 100svh;

将来 dvh を使うとしたら

dvh 自体が悪いわけではありません。例えば、以下のようなケースでは dvh のほうが自然に感じられることもあります。

  • スクロール前提のアプリ風UI
  • コンテンツ領域が動的に変わるレイアウト
  • 高さ変化がUX上問題にならない画面

判断の基準は、以下のどちらを優先するかにあります。

「安定させたいのか」
「現在の表示領域に追従させたいのか」


まとめ

  • iOS Safari の 100vh 問題は、完全に解決したわけではない
  • svh / dvh / lvh は用途に応じて使い分けるための選択肢
  • メインビジュアルのような領域では、安定性を優先して svh を選ぶのが無難
  • dvh はレイアウト変化を許容できる場面で使うのが前提となる

Safari対策は特定の単位一択で決まるものではなく、画面の役割に応じた割り切りが求められます。

お問い合わせ・お見積もりはお気軽に

内容に応じたお見積もりも無料で行います。