技術とかの雑なToday I Learnedメモ

不特定サイズの画像をアスペクト比を維持しつつ特定のサイズの領域に表示するobject-fit: contain;が便利

不特定なサイズの画像を特定のサイズのコンテナにアスペクト比を崩さずフィットさせる object-fit: contain;

投稿された画像を特定のサイズの枠内にアスペクト比を崩さず表示したいという気持ちがあったので調べた。

例として、以下のような感じだとする。

<template>
  <div class="imgContainer">
    <img :src="imgSrc" />
  </div>
</template>

<script>
// imgSrcは画像のパスを返す
</script>

<style lang="scss" scoped>
.imgContainer {
  width: 160px;
  height: 90px;

  img {
    /* ここに何かを指定する */
  }
}
</style>

このような状態のときに、imgSrcに「ユーザーが投稿した様々なサイズの画像のパス」が来るとする。

分かりやすいバラバラ度でいうと、スマートフォンで縦に撮影した写真と横に撮影した写真のようなアスペクト比の画像がランダムに来る、それに加えて縦横のサイズはランダムみたいなイメージ。

こういう場合、画像を表示する領域にどのようなスタイルを指定すればいいのか(要件にもよるけど)というのを考える必要がある。

例えば大きな表示する領域よりも大きな画像はスクロールで対応するとか。

この場合は、

.imgContainer {
  width: 160px;
  height: 90px;
  overflow: scroll;

  img {
    width: 100%;
    height: auto;
  }
}

こんな感じにすれば、160px * 90px の表示領域に表示できる部分だけ表示して、あとは上下スクロールすれば見れる、みたいな感じになる。

ただこれだと、どんな画像でも全体を 160px * 90px におさめたいという場合には要件にそぐわない(スクロールしたくないという話)

この場合に役立つのがobject-fitというプロパティ。

object-fit

object-fit - CSS: カスケーディングスタイルシート | MDN

【CSS】object-fit は CSS だけで画像をコンテナーにフィットさせてトリミングもできるとっても素晴らしいプロパティー | WEBDESIGNDAY

これを使うことで、特定のサイズの領域に画像を表示したいときに、アスペクト比を崩さずにどの部分を表示するかというのを指定できる。

このサイトは画像表示に対応していないので正直 ↑ の記事を読んでもらうほうが分かりやすいと思う。

今回の場合、スマートフォンの縦で撮った写真も横で撮った写真も 160px * 90px の枠内にスクロールなしで収めたい、という感じなので、

.imgContainer {
  width: 160px;
  height: 90px;

  img {
    width: 100%;
    height: 100%;
    object-fit: contain;
  }
}

こんな感じになる。

img タグの height と width を両方 100%にすることで、親の 160px * 90px いっぱいの画像サイズになる。

もちろん元のサイズがこれより大きければ表示枠をはみ出すんだけど、ここでobject-fit: contain;をつけることで、元の画像のアスペクト比を維持したまま 160px * 90px の画像になってくれる。

これにより縦長の画像でも横長の画像でも、160px * 90px のサイズにアスペクト比が崩れることなく全て表示できるようになり、最高。

今後も使いそうなのでこれは覚えておきたい。