結論
- どの画像ファイルがダウンロードされるかは、
sizes属性で決定される。 - その画像が表示される幅は、以下で決定される(優先順位の順番)。
- CSS での
widthプロパティ(優先順位 1位) width属性sizes属性
- CSS での
デバイスピクセル比 (DPR)
現在使用中のデバイスのデバイスピクセル比:
現在のウィンドウ幅:
各画像の幅: c-100.png (100px), c-200.png (200px), c-300.png (300px), c-400.png (400px)
実験1
コード
<img src="./c-400.png" loading="lazy"
alt="" id="img1"
srcset="./c-100.png 100w,
./c-200.png 200w,
./c-300.png 300w,
./c-400.png 400w"
sizes="200px">
結果
- sizes 属性を 200px にすることで、デバイスピクセル比 1 のデバイスでは、c-200.png が選ばれるようにしている。
実験2
コード
<img src="./c-400.png" loading="lazy"
alt="" id="img2"
width="300" height="278"
srcset="./c-100.png 100w,
./c-200.png 200w,
./c-300.png 300w,
./c-400.png 400w"
sizes="200px">
結果
- 300px で表示される。
- 300px にピッタリな c-300.png があるのに、c-200.png で 300px 表示することになる。
- width, height 属性でした通りのサイズで表示されるので、レイアウト・シフトはほぼ起きない。
実験3
コード
<img src="./c-400.png" loading="lazy"
alt="" id="img3"
width="300" height="278"
srcset="./c-100.png 100w,
./c-200.png 200w,
./c-300.png 300w,
./c-400.png 400w"
sizes="200px">
#img3 {
width: 400px;
height: auto;
}
結果
- c-400.png があるのに、c-200.png で 400px 表示することになる。
- 表示される幅・高さは CSS ファイルを読み込まないと分からないので、レイアウト・シフトが起きえる。
- 本ページでは、すぐに CSS ファイルの読み込みが始まるおかげでレンダーツリーの構築がブロックされ、その CSS ファイル内に画像の表示幅・高さの情報があるため、初期ペイントの時点で正確なサイズを空けておくことができ、レイアウト・シフトがほぼ起きない。たまたま起きないという見方ができる。
実験4: aspect-ratio を使う
コード
<img src="./c-400.png" loading="lazy"
alt="" id="img4"
srcset="./c-100.png 100w,
./c-200.png 200w,
./c-300.png 300w,
./c-400.png 400w"
sizes="200px"
style="aspect-ratio:400 / 185">
結果
aspect-ratioは単独では意味がなく、widthもしくはheightとセットで利用する。但し、sizes属性とではセットで使えないらしい。もちろん、CSS でwidthもしくはheightを指定すれば効く。sizesで決定した幅と、aspect-ratioとを合わせて高さを計算させ、レイアウト・シフトを防ぐことはできないようだ。
実験環境
- OS: Windows 10
- Webブラウザ: Chrome 89.0