htmlとCSSによる画像の出し分け(高解像度対応)

レスポンシブデザインのサイトでは、画像の大きさ(幅と高さ)を可変にする他に、高解像度(デバイスピクセル比が1より大きい)への対応が必要となっています。
javaScriptを使わずに画像の高解像度対応する方法をまとめます。

|機種|デバイスピクセル比|
|---|---|
|apple iPhoneX|3|
|hTc U11|4|

他の機種について調べる場合は、JavaScriptのwindow.devicePixelRatioで取得できます。
[JavaScriptによるユーザー情報の取得](https://qiita.com/takeshisakuma/items/8c4efdcb1ba52f5e4ae9) で記事を書きました。



## デバイスピクセル比での出し分け

```:html
<img srcset="320x240.png 1x, 640x480.png 2x, 1280x960.png 4x" src="default.png" width="320">
```

上の例の場合(大きい順に書いても、小さい順に書いても)

|デバイスピクセル比|表示される画像|
|---|---|
|1|320x240.png|
|2|640x480.png|
|4|1280x960.png|
|srcset非対応端末|default.png|


## ビューポート幅での出し分け

```:html
<img srcset="320x240.png 320w, 640x480.png 640w, 1280x960.png 1280w" src="default.png">
```

動作確認時の注意点
ブラウザの幅を変化させた場合

|ブラウザ|動作|
|---|---|
|Firefox|切り替わる|
|Edge|幅を大きくする場合は切り替わる(小さくするときはリロードすれば切り替わる)|
|Chrome|幅を大きくする場合は切り替わる(小さくするときリロードしても切り替わらないので開き直す)|
|IE|srcset非対応なのでdefault-image.pngが表示される|


上の例の場合に表示される画像
(大きい順に書いても、小さい順に書いても同じです)

|デバイスピクセル比|ビューポート幅|表示される画像|
|---|---|---|
|1|～320px|320x240.png|
|1|321px～640px|640x480.png|
|1|641px～|1280x960.png|
|1|srcset非対応端末|default.png|
|2|～160px|320x240.png|
|2|161px～320px|640x480.png|
|2|321px～|1280x960.png|
|2|srcset非対応端末|default.png|
|3|～80px|320x240.png|
|3|81px～160px|640x480.png|
|3|161px～|1280x960.png|
|3|srcset非対応端末|default.png|
(幅320px未満を考慮するケースは無いと思いますが・・・)

## sizes属性
- 画像の幅を指定する
- srcset属性をビューポート幅(w)で指定している場合のみ使用可能
- 値には、画像の横幅の表示サイズを指定
- 単位は em、rem、px、cm、pt、vw、vh、vmin、vmaxなど　(calc() 関数も使用可能))
- メディアクエリが使用可能

```:html
<img sizes="50vw" srcset="320x240.png 320w, 640x480.png 640w, 1280x960.png 1280w" src="default.png">
```

ビューポート幅が640pxの場合
画像は640pxの50vw(半分)の320pxで表示される

|デバイスピクセル比|表示される画像|
|---|---|
|1|320x240.png|
|2|640x480.png|
|4|1280x960.png|
|srcset非対応端末|default.png|

sizesにメディアクエリを使用する場合の記述方法

```:html
<img sizes="(max-width: 320px) 100vw, (max-width: 640px) 75vw, 50vw"
 srcset="320x240.png 320w, 640x480.png 640w, 1280x960.png 1280w" src="default.png">
```

## picture要素
- pictureは子要素にsourceとimgを持つことで機能する(img要素の記述は必須)
- 複数の画像リソースの中から、 ブラウザの状況に応じて希望する画像を1つ表示してくれる(読み込まれる画像は1つだけ)
- imgは読み込まれるとそこでpicture内の読み込みが終了するので、picture内の最後に記述

```:html
<picture>
  <source media="(max-width:640px)" srcset="phone.jpg">
  <source media="(min-width:960px)" srcset="tablet.jpg">
  <img src="legacy.jpg" >
</picture>
```

### source要素

|sourceの属性|内容|
|---|---|
|media|メディアクエリの指定|
|type|ファイルタイプの指定|
|srcset|切り替え幅とファイル名の指定|
|sizes|表示幅の指定|
### picture要素とsrcset属性
pictureの方がより柔軟な対応ができます。
sourceタグは srcset属性を持つので、組み合わせて利用することができます。


|secset or picture|用途|
|---|---|
|srcset|サイズ(解像度)違いの複製画像をデバイス環境に応じて切り替えるだけ|
|picture|ブラウザによって読み込む画像フォーマットを変更する、単なるサイズ違いに留まらない画像の切り替えを行える|


## 背景画像の高解像度化
メディアクエリのresolutionで出し分けを行えます。

|デバイスピクセル比|resolution(dpi)|
|---|---|
|1|96|
|2|192|
|3|288|
|4|384|

計算式 デバイスピクセル比 x 96

```:css
@media screen and (min-resolution: 96dpi) {
 
  .box {
    background-image: url("bg1x.png");
  }

}
 
@media screen and (min-resolution: 192dpi) {
 
  .box {
    background-image: url("bg2x.png");
  }
 
}
 
@media screen and (min-resolution: 288dpi) {
 
  .box {
    background-image: url("bg3x.png");
  }
 
}
 
@media screen and (min-resolution: 384dpi) {
 
  .box {
    background-image: url("bg4x.png");
  }
 
}
```