CSSで、縦横比をそろえて画像を並べる方法
縦長・横長・正方形が混ざった画像を、同じ形にそろえて並べるには、img に aspect-ratio: 4 / 3 と object-fit: cover を付けます。幅は並べる枠に合わせて決まり、高さは aspect-ratio の比から決まるので、どの画像も同じ大きさの 4:3 になります。比が合わない部分は、画像を引き伸ばさずに切り取ります。
検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。HTML と CSS だけのページを Playwright で開き、getBoundingClientRect() と getComputedStyle() の値、画面を撮った画像の色を記録しました。画像は、検証のために描いた縦横比の違う6枚の SVG です。Firefox と Safari、スマートフォンの実機は試していません。

img に aspect-ratio と object-fit: cover を付ける
HTML は、<ul> の中に画像を並べただけです。width と height の属性には、それぞれの画像の元の大きさを書いています。
<ul class="gallery">
<li><img src="img/landscape.svg" alt="横長の画像" width="600" height="400"></li>
<li><img src="img/portrait.svg" alt="縦長の画像" width="400" height="600"></li>
<li><img src="img/square.svg" alt="正方形の画像" width="500" height="500"></li>
<li><img src="img/wide.svg" alt="横に長い画像" width="800" height="300"></li>
<li><img src="img/photo.svg" alt="4:3の画像" width="640" height="480"></li>
<li><img src="img/tall.svg" alt="縦に長い画像" width="360" height="640"></li>
</ul>
CSS は次のとおりです。
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
margin: 0;
padding: 0;
list-style: none;
}
.gallery img {
display: block;
width: 100%;
height: auto;
aspect-ratio: 4 / 3;
object-fit: cover;
}
.gallery はグリッドで3列に並べ、画像は width: 100% で列の幅いっぱいにしています。高さは height: auto なので、aspect-ratio に書いた 4:3 の比から決まります。
画面の幅を 400px にして測ると、6枚とも幅 122.66px、高さ約 92px でした。幅を 800px にすると、6枚とも幅 256px、高さ 192px でした。どちらも幅と高さの比は 4:3 です。
aspect-ratio と object-fit を外すと、幅は同じ 122.66px のまま、高さは横に長い画像の 45.98px から、縦長 9:16 の画像の 218.05px までばらばらになりました。グリッドの行の高さは、その行でいちばん高い画像に合わせて 184px と 218.05px になり、低い画像の下には白いすき間が残ります。上の画像の「aspect-ratio なし」が、この並び方です。
object-fit の cover は、画像の縦横比を保ったまま枠全体を埋め、枠に収まらない部分を切り取る指定です。object-fit を書かないと、既定の fill になり、画像は枠に合わせて引き伸ばされます。
画像全体を見せたいときは contain にする
画像の端を切り取りたくないときは、object-fit: contain にします。枠の大きさは cover のときと同じ 4:3 のままで、画像全体が枠の中に収まるように縮小されます。
.gallery img {
/* ほかの指定は同じ */
object-fit: contain;
background-color: #eefafd;
}
枠のうち画像で埋まらない部分には、img の背景が見えます。横に長い 8:3 の画像では、枠の上端から 5% の位置の色が、背景に付けた薄い水色の rgb(238, 250, 253) でした。縦長 9:16 の画像では、左端から 5% の位置が同じ薄い水色でした。
切り取る位置は object-position で決める
cover で切り取るとき、どこを残すかは object-position で決めます。既定値は 50% 50% で、画像の真ん中を残し、上下(または左右)の端を同じだけ切り取ります。
縦長 2:3 の画像には、上のほうにピンクの猫の顔を描いています。既定のままだと、4:3 の枠には画像の真ん中しか入らず、猫の顔の中心は枠の上端より上に出て、切り取られました。
上の端を残したいときは、object-position: center top にします。
/* 縦長 2:3 の画像(2枚目)だけ */
.gallery li:nth-child(2) img {
object-position: center top;
}
この指定では、猫の顔の中心は枠の上から3分の1の位置に来て、その画素はピンク(rgb(216, 88, 120))でした。

位置は、top や left のようなキーワードのほかに、50% 20% のようなパーセントや 10px 0 のような長さでも書けます。画像ごとに残したい場所が違うときは、上のように、その画像だけに object-position を付けます。
height: auto を書き忘れると、属性の高さのままになる
img に width と height の属性を書いているときは、CSS に height: auto が必要です。最初の CSS から height: auto; の1行だけを消すと、画像の高さは、属性に書いた 400px、600px、500px、300px、480px、640px になりました。幅は 122.66px のままなので、枠が縦に細長くなります。getComputedStyle() で見た aspect-ratio は 4 / 3 のままでしたが、形には効いていません。画像の下の文は、ページの上から 1272px の位置まで押し下げられました(height: auto があるときは 216px)。
HTML の仕様では、img の width と height の属性は、CSS の width と height の値として扱われます。CSS で width: 100% を書くと幅は上書きされますが、高さは属性の値が残ります。MDN の aspect-ratio の説明にあるとおり、幅も高さも auto でないボックスでは、aspect-ratio は大きさに影響しません。
読み込み中も、aspect-ratio の枠で場所を取る
aspect-ratio を CSS に書いておくと、画像を読み込む前から、枠の大きさが決まります。画像のファイルを返すのを3秒遅らせて、読み込み中と読み込み後の大きさを比べました。
最初の CSS では、読み込み中も6枚とも幅 122.66px、高さ約 92px で、画像の下の文の位置は、読み込み中も読み込み後も 216px でした。
aspect-ratio を書かず、width と height の属性だけがある場合も、読み込み中から高さが決まっていました。ただし、高さは画像ごとの元の比から決まり、横長 3:2 の画像は 81.77px、縦長 9:16 の画像は 218.05px でした。このとき getComputedStyle() で見た aspect-ratio は auto 600 / 400 のように、属性の値から作られていました。HTML の仕様でも、img の width と height の属性は aspect-ratio の値としても扱われると決められています。MDN の img 要素の説明には、この縦横比を使って、読み込み前に表示に必要な場所を確保すると書かれています。
aspect-ratio も属性もない場合は、読み込み中の画像の高さは 0px でした。画像の下の文は、読み込み中は 32px の位置にあり、読み込んだ後に 434.05px の位置へ下がりました。

属性だけでも、読み込みの前後で文は動きません。ただ、取られる場所は画像ごとの元の比なので、そろえた形で場所を取るには、CSS の aspect-ratio を書きます。
使えるブラウザーのバージョン
MDN の互換性データ(@mdn/browser-compat-data 8.1.8)では、それぞれ次のバージョンから使えます。
| プロパティ | Chrome | Edge | Firefox | Safari |
|---|---|---|---|---|
aspect-ratio |
88 | 88 | 89 | 15 |
object-fit |
32 | 79 | 36 | 10 |
object-position |
32 | 79 | 36 | 10 |





