画像のサイズ調整で、Chromeでは問題なく表示されていたのにSafariでは崩れてしまう。こんな経験はないでしょうか。
ブラウザ間の表示の違いは、CSSの解釈が微妙に異なることで起こります。特に画像要素の幅指定では、fit-contentとautoの使い分けが重要なポイントになります。
1. ChromeとSafariで異なる挙動
画像の高さを指定して、幅を自動調整したい場合を考えます。アスペクト比(縦横比)を維持しながら画像を小さくしたいというのは、よくある要件です。
img {
height: 200px;
width: fit-content;
}
Code language: CSS (css)
このコードはChromeでは期待通りに動作します。画像は高さ200pxに縮小され、幅も比率を保ったまま自動調整されます。
ところがPC版のSafariでは、同じコードが正しく機能しないことがあります。画像が歪んだり、意図しないサイズになったりするのです。
1.1. fit-contentとautoの違い
そもそもwidth: fit-contentとwidth: autoは何が違うのでしょうか。
width: autoはブロック要素の初期値です。通常のdiv要素などでは、親要素の幅いっぱいに広がろうとします。width: fit-contentは、要素の中身のサイズにぴったり合わせる指定です。
たとえばボタン要素を考えてみましょう。width: autoを指定すると、ボタンは親要素の幅いっぱいに広がります。テキストが短くても、横幅は広いままです。対してwidth: fit-contentでは、テキストの長さに応じてボタンの幅が調整されます。
では画像要素ではどうでしょうか。画像は元々、画像ファイル自体が持つサイズという「中身」が存在します。そのためwidth: autoでも、画像の元サイズや指定された高さに応じた幅になります。
つまり画像要素では、autoとfit-contentの動作がほぼ同じになるはずです。
画像要素での特殊な扱い
しかし実際には、ブラウザによって解釈が異なります。
画像要素は通常、インライン要素として扱われます。width: fit-contentを指定すると、画像をブロック要素のように扱えるという利点があります。たとえばmargin: 0 autoで中央寄せする場合、fit-contentなら効果がありますが、autoのままではインライン要素なので中央寄せが機能しません。
この違いが、Safariでの挙動に影響を与えている可能性があります。Safariはfit-contentの解釈において、他のブラウザと微妙に異なる実装をしているのです。
1.2. 固定サイズコンテナに画像を収める場合(object-fit)
width: autoだけでは、画像が固定サイズのコンテナからはみ出してしまうことがあります。幅と高さの両方を指定したい場合、object-fitプロパティが役立ちます。
ここで登場するobject-fitは、width: fit-contentとは全く異なるプロパティです。
fit-contentが要素のサイズを中身に合わせるのに対し、object-fitは固定サイズの枠内での画像の収め方を指定します。
object-fitを使えば、widthとheightを両方指定しても、アスペクト比を保ったまま画像をコンテナに配置できます。
object-fit: contain
img {
width: 300px;
height: 200px;
object-fit: contain;
}Code language: CSS (css)
object-fit: containは、画像全体がコンテナ内に収まるように縮小します。画像の縦横比は維持され、コンテナより小さい場合は余白ができます。
object-fit: cover
img {
width: 300px;
height: 200px;
object-fit: cover;
}Code language: CSS (css)
object-fit: coverは、アスペクト比を維持しながらコンテナ全体を埋めます。画像がコンテナより大きい場合、はみ出た部分はトリミングされます。
どちらの方法も、すべてのモダンブラウザで安定して動作します。画像を固定サイズの枠に収めたい場合は、width: autoではなくobject-fitを使うのが適切です。
2. アスペクト比維持の正しい方法
画像のアスペクト比を維持しながらサイズ調整する場合、標準的な方法があります。
img {
height: 200px;
width: auto;
}
Code language: CSS (css)
縦または横、片方だけサイズを指定します。もう片方はautoにします。これだけです。
この方法なら、すべてのブラウザで安定して動作します。Chromeでも、Safariでも、iOSのSafariでも同じ結果が得られます。
逆のパターンも同様です。
img {
width: 300px;
height: auto;
}
Code language: CSS (css)
幅を指定して高さを自動にすれば、やはりアスペクト比は維持されます。
最大サイズを制限したい場合は、max-widthやmax-heightを使います。
img {
max-height: 200px;
width: auto;
}
Code language: CSS (css)
この指定なら、画像が200px以下の場合は元のサイズのまま、それより大きい場合だけ縮小されます。
2.1. ブラウザ互換性の重要性
width: fit-contentは、iOS Safari 9以降で対応しています。現在のiOS環境であれば問題なく使えます。
しかし対応しているからといって、すべてのケースで期待通りに動くとは限りません。今回のように、PC版Safariで問題が起きることもあります。
ブラウザ間の微妙な実装の違いは、予期しない表示崩れの原因になります。特に画像要素のような、ブラウザごとに独自の最適化が施されている要素では注意が必要です。
fit-contentは便利なプロパティですが、画像のアスペクト比維持という目的には必要ありません。width: autoの方がシンプルで、すべてのブラウザで確実に動作します。
3. まとめ
画像要素でアスペクト比を維持したサイズ調整を行う場合、width: autoが最も確実な方法です。heightだけを指定してwidth: autoにすれば、全ブラウザで安定した動作が得られます。width: fit-contentはChromeでは動作しますが、Safariでは期待通りにならないケースがあるため、画像要素のアスペクト比維持には推奨されません。