🖼️

レスポンシブ画像srcset, sizesについて理解する

2024/08/28に公開

はじめに

レスポンシブ画像というものがある。

https://developer.mozilla.org/ja/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#まとめ

まとめにあるようにレスポンシブ画像対応における問題が2つある。

  • 通信量を抑えつつ適切な画像を出したい
    • 広い画面ではサイズが大きい画像を使う(小さいとぼやける)
    • 狭い画面ではサイズが小さい画像を使う(大きいと通信量が無駄にかかる)
  • 画面幅に応じて画像を出しわけたい
    • デスクトップでは横長の画像
    • スマホでは(トリミングした)縦長の画像

上記のうち「通信量を抑えつつ適切な画像を出したい」がややこしく理解ができなかった。
何度も咀嚼してようやく考えがまとまったので、この考えについて記載する。

前提知識

ピクセルについて2つの定義がある。

  • CSSピクセル
  • デバイスピクセル
    • モニタやスマホで「画像サイズ」「解像度」などと書かれているサイズのこと
    • 物理的な画素数のこと

単に「ピクセル」と記載するとどっちのピクセルか混乱する可能性があるため、前提知識として記載した。以降は「CSSピクセル」「デバイスピクセル」と明記するようにする。

画像サイズの切替の対処方法

2通りの対処方法がある。

1. 画素密度による設定

ディスプレイの画素密度によって画像を出しわける。
これは<img>タグのsrcsetにDPRごとの画像を設定することで実現できる。

DPRとはDevice Pixel Ratioの略で、「デバイスピクセルとCSSピクセル」の比率のこと。
通常のディスプレだとDPRは1だが、高解像度のディスプレイだとDPRが1を超える。また、ディスプレイの拡大設定をすることでもDPRが変わる。

DPRが1を超える場合は、別途大きいサイズの画像を用意する必要がある(そうでないとぼやける)。
imgタグでは下記のように記述する。

<!-- 1xで指定している画像はDPR1のディスプレイで使用。2x以降も同様 -->
<img
    src="xxx.jpg"
    srcset="
        xxx.jpg 1x,
        yyy.jpg 2x,
        zzz.jpg 2.5x
    "
/>

この設定方法は分かりやすい。

2. 画面幅による設定

画面幅によって画像を出しわける。この場合は設定が複雑になる。
<img>タグのsrcsetに画像のラインナップを、sizesに画面幅ごとに使用する画像の幅を設定する。

srcsetは例えば下記のように記述する。

<img
    ...
     srcset="
        xxx.jpg 100w, 
        yyy.jpg 300w, 
        zzz.jpg 600w
    "
/>

ここでいう 100w, 300w は画像そのものの幅を表す。
(Windowsだとファイルに対して右クリック、プロパティを表示したときに出てくるサイズのこと)

ブラウザは画像を読み込むまで画像そのもののサイズを知らないので w で記述する必要がある。
参考:Explain w in srcset of image

sizesは例えば下記のように記述する。

<img
    ...
    sizes="
      (max-width: 100px) 80px,
      (max-width: 300px) 240px,
      100vw
    "
/>

ここで書いている px は CSSピクセルのこと。
メディアクエリを用いて記述する。上記だと次のようになる。

  • 画面幅が100px以下の場合は、使用する画像の幅は80px
  • 画面幅が300px以下の場合は、使用する画像の幅は240px
  • それ以外の場合は、100vw(使用する画像の幅は画面幅と同じ)

srcsetsizesを一緒に記述した<img>タグは下記のようになる。

<img
    src="xxx.jpg"
     srcset="
        xxx.jpg 100w, 
        yyy.jpg 300w, 
        zzz.jpg 600w
    "
    sizes="
      (max-width: 100px) 80px,
      (max-width: 300px) 240px,
      100vw
    "
/>

繰り返しになるが、srcsetに画像のラインナップを、sizesに画面幅ごとに使用する画像の幅を設定する。

実際に画面に表示される画像は、「画面幅」と「DPR」にて決まる。

例えば画面幅が250pxの場合、使用する画像の幅は240pxになる。240pxということで300wの画像を使うのが適切のように見える。(100wだとぼやける。600wだとサイズが大きすぎる)

だが実際にはDPRによって分岐が発生する。

  • DPRが1の場合、240px * 1 = 240なので300wの画像が使われる
  • DPRが2の場合、240px * 2 = 500なので600wの画像が使われる
    • 300Wだとぼやける

分かりづらかったところ

「1. 画素密度による設定」と「2. 画面幅による設定」で書き方が変わるところが分かりづらかった。

  • xで記述するとき、 srcsetに画像ラインナップと条件が一緒に書かれている
  • wで記述するとき、srcsetに画像ラインナップ、sizesに条件が書かれている

条件を記述する位置が異なるので、これが分かりづらくしている原因かと思った。

もう一つ分かりづらかった、というか混乱するところがあった。
これまで記載したのはあくまでどの画像を使うかの話で、ブラウザ内にどれくらいのサイズで表示するかは別途記載する必要があるということである。( <img width=300> とか cssで設定)

レスポンシブ画像の設定は、どの画像を使うかを決めるための条件設定ということを念頭に入れたい。

Discussion