サイズがバラバラな画像をレスポンシブで縦横比を揃えて表示させる

## 追記（2021/10/14）

この記事のやり方は古いやり方です。
IE や過去バージョンのブラウザに対応したい場合に参考にしてください。

今は `aspect-ratio` プロパティを使ってくださいね。
参考：[CSSのaspect\-ratioプロパティがすべてのブラウザにサポートされました、画像をアスペクト比で実装する今までとこれからの実装方法 \| コリス](https://coliss.com/articles/build-websites/operation/css/css-ways-to-create-fixed-aspect-ratio.html)


## やりたいこと

- サイズがバラバラな複数枚の画像を表示サイズを合わせて表示したい。
- レスポンシブで縦と横の比率も揃えたい。
- 画像のトリミングは縦方向も横方向も中央部分が表示できれば良い。

## CSS で画像をトリミングする方法

CSS で画像をトリミングするには…で思いつくのは2パターン。
ただしどちらも今回のやりたいことが達成できない:sob:

### object-fit を使う方法

[object-fit - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/object-fit)

> CSS の object-fit プロパティは、置換要素、例えば `<img>` や `<video>` などの中身を、コンテナーにどのようにはめ込むかを設定します。

今やりたいものだと以下のように書く。

```css
img {
  object-fit: cover;
  width: 200px;
  height: 150px;
}
```

`cover` という値は、縦横比を維持したまま要素のボックスに収まるように拡大縮小されるとのこと（上記 MDN より）

- 決められたサイズではみでた部分を非表示にはできる。
- 縦も横もピクセル数で指定する必要があるのでレスポンシブにならない。


### 親要素で囲う方法

```css
.image-trim {
  position: relative;
  overflow: hidden;
  padding-top: 60%; /* 比率 */
}
.image-trim img {
  width: 100%;
  
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  height: auto;
  transform: translate(-50%, -50%);
}
```

- 親要素で縦方向（高さ）を横方向（幅）の何パーセントと指定することでレスポンシブできる
- 縦長画像はボックスいっぱいにできる。
- ただし、横長画像は上下方向に余白ができてしまう。

こんな感じ（薄グレーの地が親要素のボックスのサイズです）
![スクリーンショット 2019-08-30 5.28.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41088/b886e3d2-53be-244b-8469-57f60ab3ffd6.png)


## 解決方法は上記2パターンをかけ合わせ

こんな感じ。

```css
.image-trim {
  position: relative;
  overflow: hidden;
  padding-top: 60%; /* 比率 */
}
.image-trim img {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  height: 100%;
  object-fit: cover;
}
```

### サンプル

サンプルとしてサイズがばらばらな画像を用意してみた。

![スクリーンショット 2019-08-29 16.53.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41088/d7d9b8ca-0a6f-2821-a57d-2994afbea042.png)

（ありえないほどめちゃくちゃだ……）
しかし、縦長の画像も横長の画像も小さいサイズだってご覧のとおり！

<img width="950" alt="スクリーンショット 2019-08-29 16.56.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41088/0ef38026-457e-850f-10c0-f515c8c87584.png">

小さいサイズの画像も拡大されてガビガビに。
レスポンシブかどうかは以下の Codepen でブラウザのウインドウ幅を変えてみてください。

<p class="codepen" data-height="338" data-theme-id="0" data-default-tab="html,result" data-user="becolomochi" data-slug-hash="zYOzdOR" style="height: 338px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="responsive trimming image">
  <span>See the Pen <a href="https://codepen.io/becolomochi/pen/zYOzdOR/">
  responsive trimming image</a> by Beco (<a href="https://codepen.io/becolomochi">@becolomochi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

### なぜそうなるのか

よく考えてみれば簡単な話で、

- img に `object-fit:cover` を指定し、縦横100%を指定することで親要素の大きさ依存でトリミングできる。
- 親要素の大きさの指定がレスポンシブになっている。
- 位置を絶対値指定することで枠内に収まる。

## トリミング位置を変えたい場合は

「トリミング位置を中央じゃなくて他がいい！」というときは、 `object-position` で変えることができる。

[object-position - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/object-position)

```css
object-position: left top; /* 左上 */
object-position: 100px 50px; /* 横方向100px 縦方向50px */
```

初期値が `50% 50%` ということで特に指定しなければ縦方向横方向ともに中央になる。

## 参考

解決の糸口になったCodepen （ありがとうございます…）
[Responsive image with picturefill and object-fit](https://codepen.io/skywalkapps/pen/ryyOjm)