で依頼する

ブログ

  1. トップ
  2. ブログ
  3. Safariだけレイアウトが崩れる時に疑うべきポイント ―「Chromeでは完璧なのに…」が起きた瞬間に読むやつ―

Web制作

Safariだけレイアウトが崩れる時に疑うべきポイント ―「Chromeでは完璧なのに…」が起きた瞬間に読むやつ―

どうも!くまweb広報ノダです!

Chromeでは問題ない。
Firefoxでも再現しない。
それなのにSafariでだけレイアウトが崩れる。

この状況に直面すると、つい「Safariは難しい」「Safariはクセがある」と言いたくなりますが、
実務で起きている多くのケースは、SafariがCSS仕様を忠実に解釈しているだけです。

つまり、Safariで崩れたという事実は、
CSSのどこかに「暗黙の期待」が残っているサインでもあります。

Safariでテキストが折り返されず突き抜ける本当の原因

Safariで発生しやすい
「Flexbox内のテキストが折り返されず横に突き抜ける」問題は、
Flexboxの初期仕様が原因です。

Flexboxでは、flexアイテムの初期値が min-width: auto になっています。
これは「テキストなど中身の最小サイズを下回らない」という意味で、
Safariはこのルールを非常に忠実に守ります。

その結果、長いテキストがあると
折り返しよりも要素の横幅拡張が優先され、レイアウトが破綻します。

この問題を解決するのが min-width: 0 です。

min-width: 0 を指定すると、
「中身がはみ出してもいいから、親要素の幅に収まれ」という挙動になり、
Safariでもテキストが正しく折り返されるようになります。

Flexbox内でテキストを扱う場合、
min-width: 0 を指定しているかどうかが、Safariでの安定性を左右する
これが本質的なポイントです。


100vh問題と、現在の標準的な解決策


iOS Safariで高さが合わない問題は、
長らくWeb制作の定番トラブルでした。

原因は、アドレスバーやツールバーの表示状態によって、
viewportの高さが動的に変化する点にあります。

以前はこの問題に対して、
JavaScriptで window.innerHeight を取得し、
CSS変数に流し込む回避策がよく使われていました。

ただしこの方法は、現在ではレガシーな対応です。

現在はCSS側で、
動的なviewportを正しく扱える単位が用意されています。

■■■■■■■■■■■■■■■■■■■■
height: 100dvh;
■■■■■■■■■■■■■■■■■■■■

dvh(Dynamic Viewport Height)を使うことで、
Safariでも実表示領域を基準に高さが計算されるため、
スクロールや初期表示でのズレが起きにくくなります。

高さに違和感が出た場合は、
JavaScriptで補正する前に、
vh単位そのものが最新の仕様に置き換わっているかを確認するのが現代的です。(※最新のiOSでは変わる可能性もあり)


position: sticky が効かない理由を正確に切り分ける

Safariでstickyが効かないとき、
Safari固有の制約に見えることがありますが、
実際には全ブラウザ共通の仕様が関係しています。

position: sticky は、
祖先要素に overflow: hidden / auto / scroll が指定されていると解除されます。

この仕様はChromeやFirefoxも同じですが、
Safariはこの条件をより厳密に解釈します。

そのため、

レイアウト調整用の overflow: hidden
スクロール制御のための overflow: auto

これらが祖先に一つでもあると、
Safariでは確実にstickyが解除されます。

ここで最近の実務で使える選択肢として、
overflow: clip があります。

■■■■■■■■■■■■■■■■■■■■
.parent {
overflow: clip;
}
■■■■■■■■■■■■■■■■■■■■

overflow: clip は、
要素をはみ出させずに表示を切り取りますが、
stickyを殺さない特性があります。

ブラウザ依存はありますが、
Safariでも有効なケースが多く、
hidden を clip に変えるだけで直ることもあります。

stickyが効かない場合は、
JavaScriptで代替する前に、
overflowの種類を見直す余地があるかを確認すると、
修正コストを抑えられます。


CSS Gridでアイテムが突き抜けるときの安全策

Gridレイアウトで、
Safariだけアイテムがはみ出す、という現象もよくあります。

これは、Gridアイテムの最小サイズが auto のままになっていることが原因です。

fr単位は便利ですが、
内容の最小サイズが優先されると、
レイアウト全体を押し広げてしまいます。

安全策として有効なのが、
最小サイズを0に明示する指定です。

■■■■■■■■■■■■■■■■■■■■
grid-template-columns: minmax(0, 1fr);
■■■■■■■■■■■■■■■■■■■■

この指定により、
内容よりもレイアウトを優先してよい、という意思が明確になり、
Safariでも安定したGridになります。


画像とレイアウトシフト(CLS)の関係


Safariで画像が一瞬巨大化する、
読み込み時にガタつく、という現象は、
レイアウト崩れではなくレイアウトシフト(CLS)として捉えるべき問題です。

特にSafariは、
画像のロード前にサイズが確定していない場合、
レイアウトを後から組み直す傾向が強く出ます。

ここで非常に重要なのが aspect-ratio です。

aspect-ratio は、
画像がロードされる前に表示領域を確定させるための、
最も強力な手段です。

■■■■■■■■■■■■■■■■■■■■
<img src="sample.jpg" width="800" height="600" alt="">
img {
aspect-ratio: 4 / 3;
max-width: 100%;
height: auto;
}
■■■■■■■■■■■■■■■■■■■■

HTMLの width / height による比率指定と、
CSSの aspect-ratio を併用することで、

画像ロード前に領域が確保される
Safariでも一瞬の巨大化が起きない
CLS対策としても有効

というメリットがあります。

Safari対策であり、
同時にSEOやCore Web Vitals対策にもなる、
非常にコスパの高い指定です。


line-clampを仕様通りに書けているか


Safariでテキストの省略が効かない場合、
記述が一部足りていないケースが多くあります。

-webkit-line-clamp は単体では機能しません。

正しく動作させるには、
以下の指定がすべて必要です。

■■■■■■■■■■■■■■■■■■■■
.text {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
■■■■■■■■■■■■■■■■■■■■

Chromeでは省略された記述でも動くことがありますが、
Safariでは仕様通りに書かれていないと無視されます。

Safariだけ効かない場合は、
この4点が揃っているかを確認するのが確実です。


Safariで崩れたときの確認順


Safariだけおかしいと感じたら、
次の順で確認すると切り分けがしやすくなります。

・Flexboxの最小サイズと縮小ルール
・vhではなくdvhを使っているか
・stickyの祖先にoverflowがないか、clipに置き換えられないか
・Gridの最小サイズが0に明示されているか
・画像のaspect-ratioが指定されているか
・webkit系プロパティが仕様通り書かれているか

Safariは特別なブラウザではなく、
仕様をそのまま返してくるブラウザです。


まとめ


Safariでのレイアウト崩れは、
対症療法ではなく、CSS仕様への理解不足が原因であることがほとんどです。

最小サイズを明示する
縮小させるかどうかを意思表示する
レイアウト確定をブラウザ任せにしない

この前提でCSSを書くと、
Safariだけ崩れる問題は再発しにくくなります。

Safari対応は、
妥協ではなく、CSSを正しく書けているかのチェックでもあります。
※本記事の内容は最新のバージョンや古いバージョンのSafariでは解釈が変わる可能性がありますのでご了承ください。