【図解】CSSだけで画像の縦横比を維持したサムネイルを表示する

サムネイルを表示するときに、サーバサイドプログラムで画像の縦横を計算してサムネイル画像を作ることがあります。しかし、場合によってはCSS3でサムネイル画像を描画したほうが実装コストが低い場合があります。ここでは、CSS3を使ってサムネイル画像をキレイに描画する方法を紹介します。

# 1. 内接・外接とは？

画像の変形方法はいろいろありますが、ここでは内接リサイズ・外接リサイズについてのみ紹介します。内接リサイズ・外接リサイズとは、画像の縦横比を維持したまま、枠のサイズにフィットするように画像のサイズを変更する描画方法です。印刷出版系の用語だそうです。

| 内接リサイズ | 外接リサイズ |
|:------------:|:------------:|
| 画像の長辺を枠に合わせ画像全体が枠内に収まるようにリサイズする。  | 画像の短辺を枠に合わせてリサイズする。枠からはみ出す部分はカットされる。 |
| ![inside] | ![outside] |

以下は、横長と縦長のサンプル画像です。これらをCSSでリサイズしてみます。

| 横長.jpeg | 縦長.jpeg |
|:----:|:----:|
|![horizontal long] | ![vertically long]|

# 2. `background-size`を使った実装

CSS3で追加された `background-size` プロパティを使います。このプロパティは、IE9+, Firefox 4+, Opera, Chrome, Safari 5+で動作します。

_background-sizeのブラウザ対応状況 [Can I use... Support tables for HTML5, CSS3, etc](http://caniuse.com/#feat=background-img-opts)より_

![can-i-use-background-size]


## 2.1 内接リサイズ

```css
.contain {
	display: inline-block;
	background-color: #ccc;
	background-position: center center;
	background-repeat: no-repeat;
	margin: 5px;
	width: 200px;
	height: 200px;
	border: 1px solid #ccc;
	background-size: contain;
}
```

```html
<span class="contain" style="background-image: url('./横長.jpeg')"></span>
<span class="contain" style="background-image: url('./縦長.jpeg')"></span>
```

### 2.1.1 描画結果

![contain]


## 2.2 外接リサイズ

```css
.cover {
	display: inline-block;
	background-color: #ccc;
	background-position: center center;
	background-repeat: no-repeat;
	margin: 5px;
	width: 200px;
	height: 200px;
	border: 1px solid #ccc;
	background-size: cover;
}
```

```html
<span class="cover" style="background-image: url('./横長.jpeg')"></span>
<span class="cover" style="background-image: url('./縦長.jpeg')"></span>
```

### 2.2.1 描画結果

![cover]

# 3. `object-fit`を使った実装

`background-size`は背景画像を使った一種のハックでしたが、CSS3では`object-fit`という画像のサムネイル表示にぴったりなプロパティが追加されています。しかし、IEやEdgeが対応待ちになっているので、IE/Edgeをサポートするサイトで今すぐ使うのは難しいかもしれません。


_object-fitのブラウザ対応状況 [Can I use... Support tables for HTML5, CSS3, etc](http://caniuse.com/#feat=object-fit)より_
![can-i-use-object-fill]

とはいえ、IE/Edgeが対応すれば、`background-size`よりもシンプルなCSSになるので、`object-fit`の実装方法も紹介したいと思います。


## 3.1 内接リサイズ

```css
.contain {
  object-fit: contain;
  width: 200px;
  height: 200px;
  background-color: #ccc;
  border: 1px solid #ccc;
}
```

```html
<img src="横長.jpeg" class="contain">
<img src="縦長.jpeg" class="contain">
```

<a href="http://codepen.io/suin/pen/xZjrar" class="btn btn-info">このCSSをCodePenで試す</a>

### 3.1.1 描画結果

![contain]

## 3.2 外接リサイズ

```css
.cover {
  object-fit: cover;
  width: 200px;
  height: 200px;
  background-color: #ccc;
  border: 1px solid #ccc;
}
```

```html
<img src="横長.jpeg" class="cover">
<img src="縦長.jpeg" class="cover">
```

<a href="http://codepen.io/suin/pen/xZjrar" class="btn btn-info">このCSSをCodePenで試す</a>

### 3.2.1 描画結果

![cover]


## 4. まとめ

CSS3の `background-size` プロパティや `object-fit` プロパティを使うとプログラムレスで画像の内接リサイズ・外接リサイズできるということを説明しました。サーバサイドで画像をリサイズしないので、画像の転送量は元画像と同じになってしまいますが、プロダクトのモックアップや初期リリース段階など、ベロシティが要求される場面で使ってみてはいかがでしょうか。

[inside]: https://qiita-image-store.s3.amazonaws.com/0/889/b9d32f5b-6206-4144-44cd-b216998c78b2.png
[outside]: https://qiita-image-store.s3.amazonaws.com/0/889/356c7f47-2e79-c511-d09c-8ee5ba49905f.png
[horizontal long]:https://qiita-image-store.s3.amazonaws.com/0/889/9f6b538b-8c23-9bce-8d3e-79ecc187a1d9.jpeg
[vertically long]: https://qiita-image-store.s3.amazonaws.com/0/889/d15e9d89-73bf-5841-9b1a-e14783fdfea8.jpeg
[contain]: https://qiita-image-store.s3.amazonaws.com/0/889/c178e213-2a4b-0fde-86cd-41cedaebde4d.png
[cover]: https://qiita-image-store.s3.amazonaws.com/0/889/1f13a622-b417-a30e-57f0-10d2be6bd32d.png
[can-i-use-background-size]: https://qiita-image-store.s3.amazonaws.com/0/889/f524c583-6117-ae50-7e00-322fb0d6723a.png
[can-i-use-object-fill]: https://qiita-image-store.s3.amazonaws.com/0/889/d80b717e-85fc-9e3c-d0f8-7c7cc2d580d6.png