CSSのobject-fitは、画像を決まった大きさの枠にどう収めるかを決めるプロパティです。
結論から書くと、画像を親要素の幅いっぱいに表示したいだけならobject-fitは必要ありません。width: 100%; height: auto;で足ります。object-fitが要るのは、幅を100%にしたうえで高さも揃えたいとき、つまり縦横比の違う画像を同じ大きさの枠に押し込みたいときです。
この記事では、object-fitの5つの値の違い、幅100%表示の書き方、比率を保ったままトリミングする書き方、そしてトリミング位置の調整までをまとめました。
スポンサーリンク
object-fitとは、画像を枠にどう収めるかを決めるCSSプロパティ
結論:object-fitは、画像や動画が「与えられた枠より大きい/小さい」ときに、はみ出す部分を切るのか、縮めて収めるのか、引き伸ばすのかを決めます。
<img>にwidthとheightを両方指定すると、画像本来の縦横比と枠の縦横比が合わない場合、画像が縦や横に潰れて表示されます。object-fitはこの潰れを防ぐための指定です。
/* 縦長の画像を正方形の枠に入れると、指定なしでは潰れる */
img {
width: 300px;
height: 300px;
object-fit: cover; /* 潰さず、はみ出した部分を切る */
}
object-fitが効くのは<img>や<video>のような置換要素だけです。<div>に書いても何も起きません。背景画像に対して同じことをしたいときはbackground-sizeを使います。
枠の大きさが決まっていないとobject-fitは意味を持たない
結論:object-fitは、幅と高さが両方確定しているときにだけ働きます。
高さがautoのままだと、画像は本来の比率で表示されるので、そもそもはみ出しも余りも発生しません。object-fitを書いても見た目は変わりません。効かないときは、まず高さが決まっているかを確認してください。
object-fitの5つの値と見え方の違い
結論:指定できる値はfill・contain・cover・none・scale-downの5つで、初期値はfillです。
| 値 | 縦横比 | 見え方 |
|---|---|---|
fill(初期値) |
維持しない | 枠いっぱいに引き伸ばす。画像が歪む |
contain |
維持する | 枠に収まるまで縮小。上下または左右に余白ができる |
cover |
維持する | 枠を埋めるまで拡大。はみ出した部分は切り取られる |
none |
維持する | 拡大も縮小もせず原寸で表示。枠より大きければはみ出した部分は切られる |
scale-down |
維持する | noneとcontainを比べて小さくなるほうを選ぶ |
サムネイル一覧のように大きさを揃えたいならcover、商品画像やロゴのように切れると困るならcontainが基本の使い分けです。
スポンサーリンク
画像を親要素の幅いっぱいに表示する
結論:幅100%で表示するだけなら、width: 100%とheight: autoの2行で済みます。object-fitもラッパーのdivも必要ありません。
img {
width: 100%;
height: auto;
}
height: autoを書いておくと、HTML側のwidth属性・height属性に引きずられて縦に潰れることがなくなります。
なお、HTML側のwidth属性とheight属性は消さないでください。ブラウザが表示前に画像の縦横比を知るために使われ、読み込み中のガタつき(レイアウトシフト)を防ぎます。
<img src="/images/sample.jpg" alt="サンプル画像" width="1200" height="800">
画像の読み込みを後回しにするloading="lazy"と組み合わせる場合は、ネイティブ Lazy Loading の改善【HTML】も参考にしてください。
幅100%のまま高さを揃えるにはaspect-ratioを使う
結論:幅は100%、高さは決まった比率に揃えたいときは、aspect-ratioとobject-fit: coverを組み合わせます。
img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
}
これで、縦長でも横長でも、すべての画像が16:9の枠にトリミングされて並びます。カードの一覧やブログのサムネイルでよく使う形です。
比率を変えたいときはaspect-ratioの値を差し替えるだけです。正方形なら1 / 1、4:3なら4 / 3と書きます。
aspect-ratioは2021年9月に主要ブラウザで使える状態(Baseline)になっているので、いまは特別な対応なしで使えます。
古いブラウザに対応するときはpadding-bottomハックを使う
結論:aspect-ratioが使えない環境向けには、ラッパー要素のpadding-bottomで高さを作り、画像を絶対配置で重ねる書き方があります。
<div class="image-container">
<img src="/images/sample.jpg" alt="サンプル画像">
</div>
.image-container {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%; /* 16:9 → 9 ÷ 16 = 0.5625 */
overflow: hidden;
}
.image-container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
padding-bottomのパーセント値は、親要素の幅を基準に計算されます。そのためpadding-bottom: 100%と書くと正方形、16:9にしたいなら56.25%です。比率ごとに数字を計算し直す必要があるのが、この書き方の面倒なところです。
スポンサーリンク
トリミングされる位置を変えるにはobject-position
結論:object-fit: coverは既定で画像の中央を残します。人物の顔が切れるようなときはobject-positionで残す位置をずらします。
img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
object-position: top; /* 上部を優先して残す */
}
object-positionにはtop・bottom・left・right・centerのほか、50% 20%のような座標も書けます。1つ目が横方向、2つ目が縦方向です。
object-fitが効かないときに確認する3点
結論:効かない原因のほとんどは「高さが決まっていない」「置換要素以外に指定している」「枠と画像の比率が最初から同じ」のどれかです。
- 高さが
autoになっていないか:heightかaspect-ratioで高さを確定させる <div>に書いていないか:object-fitは<img>や<video>などの置換要素専用。divの背景画像ならbackground-size: coverを使う- 枠と画像の縦横比が一致していないか:一致している場合はどの値を指定しても見た目が変わらない
複数の画像をグリッドで並べて大きさを揃える場面では、余白の付け方も合わせて決まります。gapプロパティでflexboxやgridに余白を入れる方法にまとめています。