Web

【HTML】img 要素の srcset 属性 と sizes 属性について

投稿日:2019年4月10日 更新日:

1. デバイスピクセル比

スマートフォンのディスプレイや Apple 製品で採用されている Retinaディスプレイは、

  • ディスプレイの物理的なピクセル数(物理ピクセル)

  • 表示に使用する論理的なピクセル数(CSSピクセル)

が同じではありません。

例えば、物理的な 3ピクセル を 表示上は 1ピクセル として扱うことによって、より滑らかに見せることができます。

そして、(物理ピクセル / CSSピクセル)を計算した値が「デバイスピクセル比」(1つのCSSピクセルに対して、物理ピクセルをいくつ割り当てるか)で、これはデバイス毎に決まっています。

デモとして、現在お使いのデバイスのデバイスピクセル比を以下に表示します。
デバイスピクセル比: (ブラウザから取得しています)

2. img 要素の srcset 属性 と sizes 属性

HTML の img 要素 には、srcset 属性と sizes 属性が用意されており、「1つの img 要素に対して、複数の画像ファイルの中から デバイスのデバイスピクセル比に最適なものを 1つだけダウンロードして表示する」という動作をさせることができます。

例えば、こんな感じで記述します。

<img src="/images/foo-600.png"
  alt="" width="600"
  sizes="600px"
  srcset="
    /images/foo-300.png 300w,
    /images/foo-600.png 600w,
    /images/foo-1200.png 1200w"
>

ざっと説明すると、以下となります。

  • sizes 属性に、表示したいサイズを指定する。
  • srcset 属性に、候補となる画像ファイルのURLを指定する(複数可)

上記コードでは 3つの画像ファイルURLが指定されていますが、ブラウザが以下の処理を自動的にやってくれます。

  1. 一番最適な画像ファイルを選ぶ
  2. ダウンロードする
  3. 表示する

それぞれの属性についてもう少し詳しく説明します。

3. sizes 属性

  • その画像をどのサイズで表示したいのか指定します。目的はこれだけです。
  • 次で説明しますが、srcset 属性で、w 単位を使った時のみ記述します。
  • メディアクエリーの条件毎に、複数の値を指定することもできます(max-widthmin-width を使って場合分けする)。
    • 通常はレイアウトが変化するブレークポイント(となるビューポートの幅)で条件を分けることが多いでしょう。
    • ブラウザは 1つ目の条件から見ていって最初に合致したものを採用します。
    • 例えば、sizes="(max-width: 767px) 70vw, (max-width: 991px) 350px, 500px" の場合、ビューポート幅が767px以下なら 70vw、991px以下なら 350px、それ以外なら 500px となります。
    • メディアクエリーで場合分けする場合は、width属性を指定してはいけません。width属性を指定すると、画像サイズが指定した値に固定されてしまい、場合分けされないからです。
  • 指定するサイズの単位は、px, em, vw などいろいろ使えます。但し、% は使えないです。

参照

4. srcset 属性

  • Webブラウザに対して、実際に使える画像の候補を伝えます(サイズ違いの画像、正確にはピクセル密度記述子が異なる画像)。
    • 「画像ファイルへのURL」と「そのファイルのサイズ(幅)」のペアを複数指定することができます。
  • 「ファイルのサイズ(幅)」は、「x 単位」と「w 単位」のどちらかで指定します。
  • Webブラウザは、sizes 属性によって決定されたサイズで画像を表示するために、srcset 属性で指定された画像の中から最適なものを選んでダウンロード・表示してくれます。
  • 基本的には、用意しているサイズ違いの画像を羅列するだけです。あとは勝手に Webブラウザが選んでくれます。

x 単位で画像ファイルのサイズを指定する場合

  • 画像の「ピクセル密度記述子 (1x2x など)」により指定します。
  • 例えば、実際は 1000px ある画像を 500px として表示したい場合は、1000 / 500 で、2x と記述することになります。
  • ブラウザは、「1x」に該当するサイズで画像を表示しようとします。そのため、sizes 属性でサイズを指定する必要がありません(その代り、メディアクエリーによる場合分けはできません)。
  • width 属性を指定する場合は、「1x」に該当するサイズをセットすることになります。

w 単位で画像ファイルのサイズを指定する場合

  • 画像の「実際のピクセルでのサイズ(単位は w で指定します)」により指定します。
  • 例えば、実際は 1000px ある画像を 500px として表示したい場合、元のサイズそのままの 1000w と記述します。
  • w 単位で指定する場合は、sizes 属性も必要になります。
  • sizes 属性によって決定されたサイズと w 単位の値の2つからピクセル密度記述子としての値に変換されます。(ピクセル密度記述子 = wの値 / sizes で決定されたサイズ)
    • Webブラウザがデバイスのデバイスピクセル比と比較して、最適な画像を選んでくれます。

参考

5. width 属性 と height 属性

2020年現在、「width 属性・ height 属性の値と、CSS での例えば width: 100%; height: auto; といった記述により、そのときのウィンドウサイズに合った画像表示サイズが算出され、レンダリングが開始される時点で画面上にそのスペースを確保することによりレイアウト・シフトを防ぐ」というブラウザの動作を利用することが望ましいとされているようです。

つまり、width 属性、height 属性、CSSでの widthheight を指定することがベストプラクティスであると言えます。

width 属性と height 属性を記述すると、sizes 属性で決定する幅が表示には使われなくなる(但しどの画像ファイルがダウンロードされるかはこれで決まります)という問題があるのですが、CSS で max-width を記述すれば、画像を表示する最大幅を指定できるため、sizes 属性で場合分けをする必要性はかなり低くなります。

以下は記述例です。

HTML

<img src="foo-500x377.png"
     alt="" loading="lazy"
     width="500" height="377"
     srcset="foo-398x300.png 398w,
             foo-500x377.png 500w,
             foo.png 759w"
     sizes="100vw">
  • sizes 属性の値は、CSS で width プロパティに指定する値に合わせます(sizes 属性で % 単位は使えません)。
  • srcset 属性で x 単位を使うのであれば、sizes 属性は必要ありません。
  • loading="lazy" を書いておくと、画面上の見える範囲に画像が現れる時点まで、画像ファイルの読み込みが行われません。指定することをお勧めします。

CSS

img {
  max-width: 500px;
  width: 100%; 
  height: auto; 
}

こう書いておけば、ウィンドウサイズが大きい場合でも画像は500pxでしか表示されず、ウィンドウサイズが小さい場合は画面一杯のサイズ(実際は画像の親要素の幅に対して最大限のサイズ)で表示してくれます。

ブラウザの新仕様

2020年になったあたりの Firefox や Chrome のバージョンから、width,height を指定すると「画像が表示される前と後でレイアウトがずれる問題」が起きにくくなっていますので、なるべく指定しておいた方がよいです。

参考

🔗 【2020年夏】imgタグにはwidthとheight属性を書くのがいいらしい | Rriver

6. デモページ

srcset 属性と sizes 属性を使ったデモページをいくつか作ってありますので参考にしてください。

7. おわりに

srcset 属性 と sizes 属性を使えば、デバイスに最適な画像を読み込ませることができるので、デバイスにとって必要以上となるデータをダウンロードしなくて済みます。

更に追加でやっておきたいこととしては、ページにとってクリティカル(すぐに表示したい)な画像に対しては、rel="preload" というのを使って画像を先読みさせるという手法です。

Web

rel=”preload” によってリソースを先読みさせる

2019.04.05

逆に、画面の下の方にある画像であれば必要になった時に画像をダウンロードすればよいので、画像の遅延読み込みを導入するとよいでしょう。

Web

Intersection Observer API を使った画像の遅延読み込み

2019.03.29

参考

関連

WordPress

WordPress に関する srcset と sizes 属性値の簡単な説明

2017.12.28

📂-Web

執筆者:labo


  1. 通りすがり より:

    参考にしようと思いましたが、下記の説明で分からなくなりました。

    「上の例の場合、(ビューポート幅が767px以下なら 70vw、それ以外でビューポート幅が 991px以下なら 350px、それ以外なら 500px となります。)」

    上の例とは??? 上に300 600 1200 という値はありますが
     70 350 500 はありません。

    全体も目を通してみましたが理解不能でした。私には基礎知識が足りないようです。

    • labo より:

      ご指摘ありがとうございます!
      確かに意味不明でしたね。
      修正致しました。

通りすがり へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Web

未ログイン状態で Facebook を開いた時に表示されるログインウィンドウを消す

目次1. Facebook の仕様変更?2. ブックマークレットの使い方3. 仕組み4. 注意点5. おわりに 1. Facebook の仕様変更? 未ログイン状態で Facebook のページを開く …

Web

インストールが可能になるための最低限のウェブサイト(PWA)を作る

インストールが可能になるための最低限のウェブサイト(PWA)を作る方法について説明します。

Web

インターネット上の情報とテレビ・新聞の情報

「ワイドナ」ネタツイートを宮崎駿監督発言と紹介? (日刊スポーツ) – Yahoo!ニュース(https://headlines.yahoo.co.jp/hl?a=20170529-018 …

Amazon からのメールは、アカウントのページから見ることができる

Amazon からのメールは、アカウントのページから見ることができます。

Web

<pre><code>タグが引き起こす モバイルユーザビリティのエラー「コンテンツの幅が画面の幅を超えています」

<pre><code>タグが、モバイルユーザビリティのエラー「コンテンツの幅が画面の幅を超えています」を引き起こしていました。