🏙️

CSSのobject-fitによる画像の切り抜き・リサイズまとめ

2020/12/02に公開

https://zenn.dev/catnose99/scraps/a1ec13e8a2d17350fbfe

CSSのobject-fitプロパティは、画像をどのようにはめ込むかを決めるものです。object-fitを使えば、決められた大きさにフィットするように画像の一部をトリミング(切り抜き)したり、リサイズしたりすることが可能です。

object-fitで画像を切り抜くイメージ

object-fitの使用イメージ

画像を中央で切り抜く例

たとえば、この画像を「幅と高さが150pxの正方形に切り抜きたい」とします。

HTMLはこんな感じとして…

<img src="/images/macho.jpeg" alt="マッチョ">

CSSで画像のwidthheightを150pxにしてみます。

img {
  width: 150px; /* 幅 */
  height: 150px; /* 高さ */
}

👆 画像自体は正方形になりましたが、もともと横長の画像だったので比率が崩れ、マッチョが細身になってしまいました。


ここでobject-fitの登場です。object-fit: coverを指定すると、画像の縦横比を保ったまま正方形に切り抜くことができます。

object-fitで画像の中央で切り抜かれる

↑ 画像が切り取られて、中央だけ(点線の部分)が表示されるわけですね。

つまり、object-fitは「150 × 150pxの枠に画像をどうはめこむか」を決めており、coverという値は「画像の比率を保ったまま、枠が埋まるように中央配置して」と指示するものというわけです。

object-fitの使い方

上の例ではobject-fitの値をcoverとしましたが、指定できる値にはいくつか種類があります。1つずつ順番に見ていきましょう。

object-fit: contain

→ 切り抜かれずに、リサイズされておさまる

img {
  width: 150px;
  height: 150px;
  object-fit: contain; /* 🖐 */
  border: dashed 1px silver; /* 分かりやすくするために */
}

値をcontainにすると、画像は切り抜かれず、画像領域にすっぽりと収まるようにリサイズされます(縦横比が保たれたまま、大きさが変わります)。画像が横長のときは、横がぴったりとくっつきます。

縦長画像でobject-fit: containを使うと…

上下がぴったりとくっつくようにリサイズされます。


object-fit: cover

→ 縦横比を保ち、はみ出る部分はトリミング

img {
  border: dashed 1px silver;
  width: 150px;
  height: 150px;
  object-fit: cover; /* 🖐 */
}

coverはページ冒頭で紹介した値です。object-fit: coverにすると、画像の縦横比を保ったまま、画像の領域におさまるように切り抜かれます。中央部分だけが残るわけですね。

縦長の画像でも同様です。上下にはみ出る部分が切り抜かれて見えなくなります。


object-fit: none

→ リサイズせず元の画像の大きさで表示

img {
  border: dashed 1px silver;
  width: 150px;
  height: 150px;
  object-fit: none; /* 🖐 */
}

値をnoneにすると、画像のリサイズがされずに、画像のオリジナルの大きさのまま表示されます。この例では画像要素の幅・高さを150pxにしていますが、マッチョ画像のオリジナルのサイズは「450 x 243px」です。オリジナルのサイズのままなので、一部しか表示されないわけですね。

縦長画像でも同じです。この画像のオリジナルサイズは「400 x 546px」なので、中央の「150 x 150px」以外は表示されません。


object-fit: scale-down

→ containと同じように縮小はするが、拡大はしない

img {
  border: dashed 1px silver;
  width: 150px;
  height: 150px;
  object-fit: scale-down; /* 🖐 */
}

少し分かりづらい値がscale-downです。画像領域(この例だと150 x 150)より大きい画像の場合には、containを指定したときと同じ表示になります。つまり、はみ出ないようにすっぽりと収まります。

縦長の画像でも「150 x 150」より大きい画像の場合にはcontainと同じように表示されます。containとの違いが出るのは、画像領域(width×height)より、小さいサイズの画像を使うときです。

↑ この画像のオリジナルサイズは「50 x 50」pxです。画像領域より小さいわけですが、object-fit: scale-downだと拡大されずにそのままのサイズで表示されています。

「大きい画像はリサイズ かつ 小さいサイズはそのまま表示」というわけですね。


object-fit: fill (初期値)

→ 縦横比をくずしてでもリサイズ

img {
  border: dashed 1px silver;
  width: 150px;
  height: 150px;
  object-fit: fill; /* 🖐 */
}

👆値をfillにすると、画像の領域を埋めるように、横も縦もピッタリとくっつきます。トリミングされずに画像が伸縮するため、元の画像の縦横比が「height : width」と異なると崩れて表示されてしまいます。

fillobject-fitの初期値値なので、特に何も指定しない場合は、object-fit: fillと同じように表示されます。

object-fitの使用例

object-fitは、サイズや縦横比がバラバラの画像を配置するときに活躍します。ここでは活用例を1つ紹介します。

画像を正方形にトリミングしてInstagramのようにグリッド表示する

Instagram風のグリッドをcSSで実現する

たとえば、CSSだけでInstagramのような正方形画像のグリッドを実現してみます。

HTML

<div class="container">
  <a href="#" class="item">
    <img src="画像1のURL">
  </a>
  <a href="#" class="item">
    <img src="画像2のURL">
  </a>
  <!-- 表示する数だけaタグを増やす -->
</div>

  • 全体をcontainerというクラスを持つ<div>で囲みます。
  • それぞれのリンク(<a>)にはitemというクラスを指定します。
  • <a>の中に画像タグを入れます。
  • <a>~</a>は表示したい数だけ増やします。

CSS

.container {
  display: flex; /* 横並び */
  flex-wrap: wrap; /* 折り返す */
}
.item {
  position: relative;
  width: 33.3%; /* 幅 */
  padding-bottom: 33.3%; /* 幅と同じ高さをつくる */
  border: solid 2px #FFF; /* 白の枠線 */
  box-sizing: border-box;
}
.item img {
  position: absolute;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

  • .containerflexをあてることで中のアイテムが横並びになります。flex-wrap: wrapなしだと3つずつで折り返されないので注意しましょう。
  • .itemの幅は1/3(33.3%)にします。少しテクニック的ですがpadding-bottom: 33.3%により、幅と高さを合わせます。これにより、1つ1つのアイテムが正方形になります。
  • imgwidthheightを100%にすることで、正方形の.itemと合わせます。
  • imgobject-fit: coverを指定することで正方形にトリミングします。

このように、object-fitは、自分のイメージ通りのサイズに画像をはめこみたいときに便利です。ちなみにobject-fitは画像(img要素)だけでなく、動画(video要素)に使用することもできます。

Discussion