
テスクトップ・タブレット・モバイル…今やサイトは色々な端末で見られます。またRetinaディスプレイなど高解像度のディスプレイも多くなってきました。
見せる側としても最高な状態のものを見せたいので、Webサイトを見る端末の進化によって対応が必要になります。
PC用の大きな画像をそのままスマホでも読み込んでいると、表示が遅くなる原因になります。反対に小さな画像を使うと、高解像度のディスプレイではぼやけて見えてしまいます。それぞれのデバイスに応じた最適サイズや解像度に最適な画像を読み込ませる表示するように切り替えることは、Webサイト制作において大切なことです。
できる限り表示速度を早めた上できれいな画像を表示させるためには、適切な画像が表示されるよう切り替えることが必要です。imgタグのsrcset属性を使えば、画面に合ったサイズの画像をブラウザに選んでもらえます。
srcset属性とは
imgタグで画像をレスポンシブに切り替えるためにsrcset属性とsizes属性を使用します。
srcset属性は、imgタグに「この中から画面に合う画像を選んでね」という画像の候補を指定するための属性です。以下のような切り替えをしたい場合に設定します。
- ディスプレイの解像度に合わせて画像を切り替える
- 画面サイズに合わせて画像を切り替える
- 画面サイズ別に表示する画像を変更する
ブラウザは画面の幅や解像度などを見て、候補の中からちょうどいいサイズの画像を1つだけ読み込みます。
【記述例】
<img
srcset="img_s.jpg 320w,
img_m.jpg 640w,
img_l.jpg 1280w"
src="img_l.jpg"
sizes="(max-width:1280px) 100vw, 1280px">
<img
src="img_s.jpg"
srcset="img_s.jpg 640w, img_m.jpg 1280w, img_l.jpg 1920w"
sizes="100vw"
alt="海辺の写真"
width="1920"
height="1280">
src属性は sercset に対応していないブラウザの場合に読み込ませる画像を書いておきます。
srcsetには「画像のパス」と「記述子(1xや640wなど)」を半角スペースでつなげて書き、複数の画像はカンマで区切ります。
記述子には次の2種類があり、どちらを使うかで書き方が変わります。
| 記述子 | 意味 | 向いている場面 |
|---|---|---|
x | 画面の解像度(デバイスピクセル比)に合わせて選ぶ | ロゴやアイコンなど、表示サイズが決まっている画像 |
w | 画像ファイルの幅をもとに、表示幅に合わせて選ぶ | 記事内の画像やメインビジュアルなど、画面幅によって表示サイズが変わる画像 |
画面の解像度に合わせて切り替える(x記述子)
表示サイズが決まっていて、ディスプレイの解像度の違いによって画像の表示を切り替えたい場合は 1x・2xで指定するのがシンプルです。
<img
src="img.jpg"
srcset="img.jpg 1x, img@2x.jpg 2x"
alt="Example image"
width="600"
height="400">通常の画面ではimg.jpg、Retinaディスプレイのようにデバイスピクセル比が2の画面では、2倍サイズのimg@2x.jpgが表示されます。600px×400pxで表示するなら、img.jpgは600px×400px、img@2x.jpgは1200px×800pxの画像を用意します。
srcに指定した画像は1xの画像としても扱われるので、次のように省略して書くこともできます。
<img src="img.jpg" srcset="img@2x.jpg 2x" alt="Example image" width="600" height="400">表示幅に合わせて切り替える(w記述子とsizes属性)
画面幅によって表示サイズが変わる画像は、w記述子とsizes属性を組み合わせます。
<img
src="img_s.jpg"
srcset="img_s.jpg 640w, img_m.jpg 1280w, img_l.jpg 1920w"
sizes="100vw"
alt="Example image"
width="1920"
height="1280">640wは「画面幅が640pxのとき」という意味ではなく、「この画像ファイルの幅は640px」という意味です。ここを画面幅の指定だと思ってしまうと、思ったとおりに画像が切り替わりません。
sizesは「画像を表示する幅の目安」
sizes属性には、その画像がページ上でどのくらいの幅で表示されるかを書きます。ブラウザはHTMLを読み込んだ時点ではまだCSSを読んでいないので、画像の表示幅がわかりません。そこで「だいたいこのくらいの幅で表示される」と教えておきます。
単位はpx, em, vwが使用可能で%は使えません。
sizes属性のデフォルトは100vw。50vwにすることで画面サイズの半分のサイズ画像が読み込まれることになります。以下のコードなら、1280pxを越えるまではimg-640.jpgが表示されます。
<img src="img.jpg"
sizes="50vw"
srcset="img-640.jpg 640w, img-1280.jpg 1280w"
alt="Example image">ブラウザは「sizesの幅 × 画面の解像度」を計算し、それに近い幅の画像をsrcsetの候補から選びます。
たとえば上の例(sizes="100vw")を、画面幅375px・デバイスピクセル比3のスマホで表示するとなると、1125pxの幅が必要になります(計算: 375 × 3 = 1125)。
srcset="img_s.jpg 640w, img_m.jpg 1280w, img_l.jpg 1920w" なら、基本的にはimg_m.jpgが選ばれます。同じスマホでも解像度が1の画面ならimg_s.jpgで足ります。
この数字の指定であれば、解像度の高さも考慮してくれます。
→ 640pxの画面サイズでも、Retinaの場合img-1280.jpgを表示。
この指定方法だけで表示に問題なければmedia属性は不要です。
sizesを書かずにw記述子を使った場合は、sizes="100vw"(画面幅いっぱい)として扱われます。記事の本文幅など、画面幅いっぱいに表示しない画像でsizesを省略すると、必要以上に大きな画像が読み込まれてしまいます。
sizesにメディアクエリを使う
画面幅によって画像の表示幅が変わる場合は、sizes属性にメディアクエリを組み合わせます。
<img
src="img_s.jpg"
srcset="img_s.jpg 640w, img_m.jpg 1280w, img_l.jpg 1920w"
sizes="(max-width: 768px) 100vw, 50vw"
alt="Example image"
width="1920"
height="1280">画面幅768px以下では画面幅いっぱい(100vw)、それより広い画面では画面幅の半分(50vw)で表示される、という意味です。条件は左から順に判定され、最初に当てはまった値が使われます。最後の値には条件を付けず、どれにも当てはまらなかったときの幅を書きます。
コンテンツの幅に上限がある場合は、次のようにpxで指定することもできます。
sizes="(max-width: 1280px) 100vw, 1280px"
sizesとCSSの幅をそろえる
sizesはブラウザが画像を選ぶための目安で、実際の表示サイズはCSSで決まります。sizesとCSSで指定した幅がずれていると、小さすぎる画像でぼやけたり、大きすぎる画像を読み込んだりする原因になります。CSSでレイアウトを変えたときは、sizesもあわせて見直しておきましょう。
遅延読み込みの画像はsizes=”auto”も使える
loading="lazy"で遅延読み込みしている画像には、sizes="auto"を指定できます。遅延読み込みの画像はレイアウトが決まってから読み込まれるので、ブラウザが実際の表示幅を見て画像を選んでくれます。sizesの値を自分で計算しなくて済むのが便利なところです。
<img
src="img_s.jpg"
srcset="img_s.jpg 640w, img_m.jpg 1280w, img_l.jpg 1920w"
sizes="auto, (max-width: 768px) 100vw, 50vw"
loading="lazy"
alt="Example image"
width="1920"
height="1280">sizes="auto"はChromeとEdge(126以降)、Firefox(150以降)が対応していて、Safariは対応が進んでいる段階です。対応していないブラウザではautoの後ろに書いた値が使われるので、上の例のように従来の指定も続けて書いておきます。
ファーストビューに表示される画像にはloading="lazy"を付けないようにしましょう。読み込みが遅れて、ページの表示が遅くなる原因になります。
WordPress 6.7以降では、遅延読み込みの画像にsizes="auto"が自動で追加されるようになっています。
ファーストビューの画像を早く表示させる方法
widthとheightも書いておく
srcsetを使う場合も、<img>にはwidth属性とheight属性を書いておきます。
width・heightがあると、画像が読み込まれる前からブラウザが表示する場所を確保できるので、読み込み後にレイアウトがずれるのを防げます(CLSの改善)。候補の画像はどれも同じ縦横比にしておき、その比率になる数値を書きます。
CSSではheight: autoを指定しておくと、縦横比を保ったまま画面幅に合わせて縮小されます。
img {
max-width: 100%;
height: auto;
}画像が思ったとおりに切り替わらないとき
大きい画像がキャッシュされている
srcsetの中からどの画像を選ぶかは、最終的にはブラウザの判断にまかされています。すでに大きい画像をキャッシュしていれば、画面を小さくしても新しく小さい画像を読み込まず、キャッシュ済みの大きい画像を使うことがあります。通信量を減らすためのブラウザの仕様どおりの動きです。
画面幅を変えながら確認するときは、デベロッパーツールの「ネットワーク」タブで「キャッシュを無効にする」にチェックを入れるか、シークレットウィンドウで確認しましょう。
実際に読み込まれた画像を確認する
どの画像が使われているかは、デベロッパーツールで確認できます。「要素」パネルで<img>を選択した状態でコンソールに$0.currentSrcと入力すると、実際に表示されている画像のURLが表示されます。
画面の解像度も計算に入っている
スマホで確認すると、思ったより大きい画像が読み込まれていることがあります。スマホの多くはデバイスピクセル比が2〜3なので、sizesの幅の2〜3倍の画像が選ばれるのは正しい動きです。
imgタグとpictureタグの使い分け
画像の表示切り替えはpictureタグでもimgタグでもできます。レスポンシブで切り替えたい画像によって、pictureタグとimgタグを使い分けます。
imgタグのsrcsetは、同じ画像のサイズ違いを出し分けるためのものです。どの画像を使うかはブラウザが選ぶので、スマホとPCでトリミングの違う画像を確実に出し分けたい場合には向いていません。
| やりたいこと | 使うもの |
|---|---|
| 同じ画像のサイズ違いを、画面幅や解像度に合わせて出し分けたい | imgタグのsrcset・sizes |
| スマホとPCでトリミングや構図の違う画像を見せたい | pictureタグ(media属性) |
| AVIFやWebPに対応したブラウザにだけ軽い画像を読み込ませたい | pictureタグ(type属性) |
画像の見た目を変えたい場合や、画像形式を出し分けたい場合はpictureタグを使います。
pictureタグの使い方
まとめ
imgタグのsrcset属性で画像の候補を指定すると、ブラウザが画面に合ったサイズの画像を選んでくれます。
どの画像を選ぶかはブラウザが決めるので、確認するときはキャッシュを無効にすることをお忘れなく。
表示サイズが決まっている画像は1x・2x、画面幅によって表示サイズが変わる画像はwとsizesで指定します。wは画面幅ではなく画像ファイルの幅、sizesは画像を表示する幅の目安です。
sizesはCSSで指定した表示幅と揃えましょう。遅延読み込みの画像ならsizes="auto"も使えます。