HTMLにimg要素で画像を表示する 2020年版

<h2>基本形</h2>
```html
<img src="sample.jpg" alt="画像">
```
基本形は非常にシンプルですね。

---

<h2>レスポンシブ画像1: srcset属性</h2>
```html
<img src="sample.jpg"
     srcset="sample@2x.jpg 2x, sample@3x.jpg 3x"
     alt="画像">
```
`srcset`属性を使うとRetinaディスプレイ/高解像度ディスプレイに対応した画像を置くことができる。

**参考**

 - [レスポンシブ画像 - MDN](https://developer.mozilla.org/ja/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images)

---

<h2>レスポンシブ画像2: sizes属性</h2>
```html
<img srcset="sample-320w.jpg 320w,
             sample-480w.jpg 480w,
             sample-800w.jpg 800w"
     sizes="(max-width: 320px) 280px,
            (max-width: 480px) 440px,
            800px"
     src="sample-800w.jpg"
     alt="画像">
```

`sizes`属性を使うとさまざまなディスプレイサイズに対応できる。

**参考**

 - [レスポンシブ画像 - MDN](https://developer.mozilla.org/ja/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images)

---


<h2>レスポンシブ画像3: アートディレクション（画像の切り替え）</h2>

```html
<picture>
  <source media="(max-width: 799px)"
          srcset="sample-480w-sp.jpg">
  <source media="(min-width: 800px)"
          srcset="sample-800w.jpg">
  <img src="sample-800w.jpg"
       alt="画像">
</picture>
```

`picture`要素と`source`要素を組み合わせるとディスプレイサイズなど条件別にまったく別な画像を出し分けることもできる。

**参考**

 - [アートディレクション - MDN](https://developer.mozilla.org/ja/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#Art_direction)

---


<h2>レスポンシブ画像4: webpを使う</h2>
```html
<picture>
  <source type="image/webp"
          srcset="sample.webp">
  <img src="sample.png"
       alt="画像">
</picture>
```
webpはGoogleが開発した画像形式で、jpegなど従来型画像形式よりも軽量であるためwebパフォーマンス面で有利になる。<br>前述のアートディレクションと同様の方法で表示切り替え可能。<br>IEとSafariは現在のところwebp非対応。

**参考**

- [レスポンシブイメージのネイティブサポート ほかの画像フォーマットを読み込む - html5rocks](https://www.html5rocks.com/ja/tutorials/responsive/picture-element/#toc-file-type)

---


<h2>レスポンシブ画像5: 画面サイズおよび解像度ごとの出し分けとwebp/pngの出し分けを律儀に行ってみる</h2>
```html
<picture>
  <source type="image/webp"
          media="(min-width: 1200px)"
          srcset="sample-lg.webp 1x, sample-lg@2x.webp 2x">
  <source type="image/webp"
          media="(max-width: 1199px)"
          srcset="sample-md.webp 1x, sample-md@2x.webp 2x">
  <source type="image/webp"
          media="(max-width: 380px)"
          srcset="sample-sm.webp 1x, sample-sm@2x.webp 2x">
  <source type="image/png"
          media="(min-width: 1200px)"
          srcset="sample-lg.png 1x, sample-lg@2x.png 2x">
  <source type="image/png"
          media="(max-width: 1199px)"
          srcset="sample-md.png 1x, sample-md@2x.png 2x">
  <source type="image/png"
          media="(max-width: 380px)"
          srcset="sample-sm.png 1x, sample-sm@2x.png 2x">
  <img src="sample.png"
       alt="画像">
</picture>
```
画像一枚を表示するためにHTML記述量がびっくりするほど増えます:sweat_smile:

---
<h2>サーバー側でwebp出し分け設定を行う方法</h2>

前項のようにHTMLの記述量が増えることを防止するために、サーバー側の設定変更で対応する方法があります。Apache/.htaccessを使う方法とNginxを使う方法に付いては、下記が大変参考になりました。

**参考**

- [2. htaccessでファイルを差し替える - WebP対応をしたらサイトが軽くなったので、最も対応しやすい方法を解説します - イロコトのブログ](https://irokoto.co.jp/blog/20200527/post-8#2_htaccess)
- [nginxにおけるWebP画像の選択的レスポンスの設定方法](https://qiita.com/miyanaga/items/94447efae0bf767b9f2b)

---


<h2>decoding属性</h2>
```html
<img src="sample.jpg"
     decoding="async"
     alt="画像">
```
`decoding="async"` 指定で、画像は非同期で復号化される。HTML Living Standard標準化仕様で、IE以外の主要ブラウザで使用可能。
<p>画像のデコーディング(復号)を非同期にすることで、表示時間が短縮される。</p>

**参考**

- [decoding="async" VS loading="lazy" — ブログ | 株式会社Spelldata](https://spelldata.co.jp/blog/blog-2019-12-19.html#:~:text=decoding%E5%B1%9E%E6%80%A7%E3%81%AF%E3%80%81%E7%94%BB%E5%83%8F%E3%81%AE,%E3%82%92%E4%B8%80%E7%B7%92%E3%81%AB%E5%87%BA%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)

---


<h2>loading属性</h2>
```html
<img src="sample.jpg"
     loading="lazy"
     width="640"
     height="360"
     alt="画像">
```
- `loading="lazy"`指定で画像の遅延読み込みができる。
- HTML Living Standard標準化仕様ですが、IEとSafariは現在のところ非対応。
- 仕様上`width` / `height` 属性を書いてあげないと動作しない。

**参考**

- [decoding="async" VS loading="lazy" — ブログ | 株式会社Spelldata](https://spelldata.co.jp/blog/blog-2019-12-19.html#:~:text=decoding%E5%B1%9E%E6%80%A7%E3%81%AF%E3%80%81%E7%94%BB%E5%83%8F%E3%81%AE,%E3%82%92%E4%B8%80%E7%B7%92%E3%81%AB%E5%87%BA%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)
- [Firefox 75、HTML の指定のみで動作する画像遅延読み込み （loading="lazy"） に正式対応 - WWW Watch](https://hyper-text.org/archives/2020/04/firefox_75_lazy_loading.shtml)
- [Native image lazy-loading for the web! - Addy Osmani](https://addyosmani.com/blog/lazy-loading/)
- [【HTML】loading属性で“lazy”を指定する場合、widthとheight属性が必要](https://qiita.com/kingpanda/items/1e0b7d14dc2fdb06fc9a)

---


<h2>decoding="async"とloading="lazy"を両方書くとどうなるか</h2>
```html
<img src="sample.jpg"
     decoding="async"
     loading="lazy"
     width="640"
     height="360"
     alt="画像">
```

- `decoding="async"`と`loading="lazy"`は、併記しても両立しない。両方書くと`loading="lazy"`が優先される。<br>
- `loading="lazy"`が指定されていてもページ読み込み時にビューポート内の画像は遅延せず読み込まれる。

- ということは大量の画像がありスクロールするページでは`loading="lazy"`、そうでなければ`decoding="async"`といった具合にケースによって使い分けるのが良いのではないか（自信なし）:rolling_eyes:

**参考**

- [decoding="async" VS loading="lazy" — ブログ | 株式会社Spelldata](https://spelldata.co.jp/blog/blog-2019-12-19.html#:~:text=decoding%E5%B1%9E%E6%80%A7%E3%81%AF%E3%80%81%E7%94%BB%E5%83%8F%E3%81%AE,%E3%82%92%E4%B8%80%E7%B7%92%E3%81%AB%E5%87%BA%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)

---

<h2>【重要】width / height属性の仕様変更</h2>
```html
<img
    src="sample.jpg"
    width="640"
    height="360"
    alt="画像">
```
2019年10月にWHATWGが標準化。<br>
`width` / `height` 属性を記述することで**layout Shift**（画像ロード時の表示のガタつき）が起きなくなる。<br>従来`width` / `height` 属性はピクセル単位のサイズのことだったが、仕様変更により同時に**アスペクト比**を表すことができるようになった。

---


<h3>layout Shift（画像ロード時の表示のガタつき）</h3>
実際の動きはこちらを参照。

 - [Optimize Cumulative Layout Shift - web.dev](https://web.dev/optimize-cls/#images-without-dimensions) 

Layout ShiftはLighthouse v6より新指標CLSとしてパフォーマンス計測対象となっている。
**参考**

- [画像による Layout Shift が無くなる Web がやって来る - mizdra's blog](https://www.mizdra.net/entry/2020/05/31/192613)
- [Cumulative Layout Shift (CLS) - web.dev](https://web.dev/cls/)
- [【重要】コアウェブバイタルとは？ グーグルのUX指標LCP/FID/CLSの意味や基準値をわかりやすく解説【SEO情報まとめ】 - Web担当者Forum](https://webtan.impress.co.jp/e/2020/06/05/36210)
- [【2020年夏】imgタグにはwidthとheight属性を書くのがいいらしい](https://parashuto.com/rriver/development/img-size-attributes-are-back)

---


<h2>全部のせで最適化してみる</h2>
**レスポンシブ画像 + webp対応 + 非同期復号 + Layout Shift対策** 全部のせで画像を最適化したコードは次のようになりました。

```html
<picture>
  <source type="image/webp"
          srcset="full_optimized.webp 1x, full_optimized@2x.webp 2x, full_optimized@3x.webp 3x">
  <img src="full_optimized.png"
       srcset="full_optimized@2x.png 2x, full_optimized@3x.png 3x"
       decoding="async"
       width="640"
       height="360"
       alt="画像">
</picture>
```