【CSS】画像の縦横比を固定したトリミング方法(レスポンシブにも対応)

以下のような実装をしたい場合に役立つ記事です。

  • 画像の縦横比(アスペクト比)を維持したまま、レスポンシブにサイズを変えたい
  • サイズの異なる画像を並べて表示する際に、同じサイズで綺麗に表示したい
  • WordPress化(CMS化)後に、どんなサイズの画像に変更されても同じ比率で表示したい

特にWordPressの記事サムネイル画像など、どんなサイズの画像が挿入されるかわからない箇所の場合、表示崩れを起こさないために画像の縦横比を固定し、その領域をはみ出す部分をトリミングする実装が必要になります。

そのようなケースを想定したコーディング方法を、

  • aspect-ratioを使用する方法
  • padding-topを使用する方法

の2つに分けて詳しく解説します。

目次

aspect-ratioを使用する方法(最新版)

CSSの「aspect-ratio」は、アスペクト比(縦横比)を指定することができるプロパティです。
2021年頃にリリースされた比較的新しいプロパティですが、現在はIEを除く全ての最新ブラウザでサポートされています(ブラウザ対応状況はこちら

結論

aspect-ratioを使用し、画像の縦横比を固定したままトリミングしたい場合、以下のように記述します。

.img {
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

aspect-ratio使い方解説

aspect-ratioには、width / heightの比率を指定します。

例として、以下の縦長の画像をwidth : height = 4 : 3の比率で表示させる場合を見てみましょう。

指定のアスペクト比で表示させたい元画像の例

CSSには以下のように記述します。

例1:

.img {
    aspect-ratio: 4 / 3;
}

aspect-ratioの値は比率を指定すれば良いので、例えばデザイン上のwidthが640px、heightが480pxの要素の場合、以下のように直接的に指定することも可能です。(分数を約分する必要はない)

例2:

.img {
    aspect-ratio: 640 / 480;
}

これにより、元々は縦長だった画像を、width : height = 4 : 3の比率の範囲内に収めることができます。
しかし、デフォルトでは画像の全てを指定のアスペクト比の範囲内に収めようとするため、以下のように潰れた表示になってしまいます。

指定のアスペクト比の領域内に表示させた画像が潰れて見える例

これを防ぐためには、CSSでobject-fit: cover;を指定します。

.img {
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

これにより、画像自体のアスペクト比を維持したまま、指定の範囲からはみ出す部分をトリミングできます。

画像自体のアスペクト比を維持したまま、表示領域からはみ出す部分をトリミングした例

(デフォルトでは上下左右中央の位置でトリミングされますが、object-positionプロパティでトリミング位置の調整も可能です)

widthを%やvw指定し、ブラウザ幅に応じて幅を変化させる場合でも、指定したaspect-ratioを維持したまま自動でサイズが変動します。

.img {
    width: 95%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}
画面幅が変わってもアスペクト比を維持したまま画像サイズが変動する例

padding-topを使用する方法(古いブラウザでも可)

IEや古いバージョンのブラウザにも完全対応したい場合はaspect-ratioは使用できないため、padding-topを使用する方法(paddingハック)を使います。

結論

padding-topを使用し、画像の縦横比を固定したままトリミングしたい場合、以下のように記述します。
(※ aspect-ratioを使う方法と違い、画像を包括する親要素のhtmlタグが必要になります)

<div class="img_wrapper">
    <img src="/image.jpg" alt="" class="img" />
</div>
.img_wrapper {
    position: relative;
}

.img_wrapper::before {
    content: "";
    display: block;
    padding-top: 75%;
}

.img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

padding-top使い方解説

考え方としては、指定のアスペクト比に設定した画像の枠(.img_wrapper)を用意し、その枠内で画像を幅&高さ100%で絶対位置表示させるという流れです。

まずは、.img_wrapper要素を、画像の絶対位置表示の基準となるようposition: relative;に設定します。

.img_wrapper {
    position: relative;
}

ここがポイントで、.img_wrapperの擬似要素に、幅に対する高さの割合をpadding-topで指定します。
padding-topの値はheight / width * 100 [%] という計算で求められます。

.img_wrapper::before {
    content: "";
    display: block;
    padding-top: 75%;
}

これにより、幅に対する高さの割合で算出された余白が設けられ、.img_wrapper要素は固定のアスペクトを持つ四角形領域となります。

padding-topプロパティにより、固定のアスペクト比を持つ四角形領域が出来上がった例

.img_wrapper要素自体にpadding-topを指定してもよいですが、.img_wrapperのwidthが100%でない場合は計算が面倒になります。そのため、.img_wrapperの擬似要素(::beforeでも::afterでも可)にpadding-topを指定しています。

あとは、画像を先程の.img_wrapper要素の枠一杯に表示させるため、以下のように記述すれば完成です。

.img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

まとめ:CMS化を想定した画像コーディングをマスターしよう

画像の縦横比(アスペクト比)を固定したままトリミングする方法を、

  • aspect-ratioを使用する方法
  • padding-topを使用する方法

の2パターンに分けて解説しました。

WordPressなどのCMS化により自由に画像を設定できる箇所の場合、どんなサイズの画像が挿入されても表示を崩さないために、今回解説した内容がとても重要になります。
CMS化を想定した画像のコーディング方法をマスターしておきましょう。

内容が良かったらSNSでシェアしていただけると嬉しいです!
目次