Insights

技術情報

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

iOS Safari における 100vh 問題は、長いあいだフロントエンド開発者を悩ませてきました。

最近はあまり話題に上がらなくなったこともあり、
「もう解決したのでは?」と思われがちですが、実際にはそうではありません。

正確に言うと、問題そのものが解決したわけではなく、回避手段が増えた、という状態です。

この記事では、実際に開発中のサイトで検証した結果をもとに、

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

このあたりを整理しておきます。


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

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

ところが iOS Safari には、

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

という特徴があります。

その結果、

  • 初期表示では高さが足りない
  • スクロールすると要素がはみ出したり、逆に余白が出たりする

といった現象が起きやすくなります。

これが、いわゆる「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としてはあまり好ましくありません。

そのため今回は、

height: 100vh;
height: 100svh;

とし、dvh は外す判断をしました。


将来 dvh を使うとしたら

dvh 自体が悪いわけではありません。

例えば、

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

こういったケースでは、むしろ dvh のほうが自然に感じることもあります。

要は、

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

どちらを優先するか、という判断になります。


まとめ

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

Safari対策は「これ一択」という話ではなく、
画面の役割に応じた割り切りが重要だと感じています。

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

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