pictureタグ レスポンシブに画像を切り替える

HTMLの<picture>ピクチャータグを使えば、CSSやJavaScriptを使わなくても、画像をレスポンシブに切り替えることができます。

<picture>はHTML5で登場しましたが、IEをのぞけば、すべての主要ブラウザで使用できます。
ブラウザ対応状況へスキップ

pictureタグでできること

<picture>により実現できることは次の2つです。

  • 画面幅によって、表示する画像を切り替える
  • ブラウザが対応していない形式の画像なら、別の画像を表示する

レスポンシブ画像のデモ

画面(ビューポート)の幅に応じて、別の画像を表示することが可能になります。これは「レスポンシブ画像」や「レスポンシブイメージ」などと呼ばれます。
👉デモページ

また、<picture>を使えば「WebP形式の画像に対応していないブラウザなら、PNG画像を表示する」といった出し分けも可能になります。

pictureタグの使い方

具体的な使い方を解説していきます。

sourceとimgタグと使う

<picture>タグは、複数の<source>と、1つの<img>を囲う形で使います。

<picture>
  <source srcset="候補1の画像URL" 属性 />
  <source srcset="候補2の画像URL" 属性 />
  <img src="候補4の画像URL" alt="~" />
</picture>

👆それぞれに表示する画像候補のURLを指定します。この中からどれか1つの画像が表示されます。<img>は1つだけですが、<source>はいくつ入れてもOKです。

条件に当てはまる画像1つだけが表示される

ブラウザは以下のような流れで、<source><img>のうちから表示する画像を1つ選びます。

表示する画像の選ばれ方

  1. <source>上から1つずつ順番に読んでいく
  2. <source>の属性に指定された条件を読む
  3. 条件に当てはまれば、その画像を表示。当てはまらなければ、下の<source>へと進む
  4. <source>のどれにも条件が当てはまらなければ<img>を表示する

つまり👇このような優先順位で判定されます。

表示される優先順位
<picture>
  <source .../><!-- 🥇優先順位1 -->
  <source .../><!-- 🥈優先順位2 -->
  <source ... /><!-- 🥉優先順位3 -->
  <img ... /><!-- 😿どれも当てはまらなければimgを表示 -->
</picture>

sourceタグの属性を指定する

<source>タグの属性で「どの場合に、どの画像を表示するか」という条件を指示します。

画像URL(srcset)必須

<source srcset="画像のURL" />

▼例
<source srcset="/learning/images/example.png" />

👆srcsetには画像URLを指定します。<img src="○○">と同じようにURLを入れればOKです。条件に当てはまったときは、ここに指定した画像が表示されます。

メディアクエリ(media)

<source srcset="画像のURL" media="メディアクエリ" />

▼例
<picture>
  <source srcset="~" media="(min-width: 1000px)"/><!-- 幅1000px以上なら表示 -->
  <source srcset="~" media="(min-width: 700px)"/><!-- 幅700px以上なら表示 -->
  <source srcset="~" media="(min-width: 500px)"/><!-- 幅500px以上なら表示 -->
  <img ... /><!-- それ以外で表示 -->
<picture>

👆media属性には、メディアクエリ(画面幅に応じた条件)を指定します。(min-width: ○○px)と書けば「画面幅が○○px以上なら…」という意味になります。画面サイズに応じて画像を切り替えたいときに使用します。

😺さきほど説明した通り<source>は上から順番に読み込まれていくので、配置する順番に注意しましょう。条件に合致する<source>が見つかった時点で画像は表示され、他の画像は読み込まれません。

画像の形式(type)

<source srcset="画像のURL" type="画像の形式" />

▼例
<picture>
  <source srcset="/sample.webp" type="image/webp"/>
  <img src="/sample.png" /><!-- ブラウザがwebpに対応していない場合に表示 -->
<picture>

👆type属性には、画像の形式を「MIMEタイプ」で指定します(例:type="image/webp")。JPEG、PNG、GIFは全ブラウザで対応しているため、<source type="○○">に指定する意味はありません。WebPなど、未対応ブラウザがある画像を挿入したい場合に指定します。

😺WebPはGoogleが開発している次世代の画像形式です。「高い画質を保ちつつ、軽量」と優れているのですが、未対応のブラウザがあります(WebPの対応ブラウザ)。<picture>を使えば、対応ブラウザでのみWebP画像を表示できるわけですね。

レスポンシブに別画像に切り替えるサンプル

ここからは具体的なサンプルコードを紹介します。まずは<picture>タグを使って画面幅に応じて、別の画像を表示するサンプルです。

HTML
<picture class="sample">
  <source srcset="画像1URL" media="(min-width: ○○px)" /><!-- ○○px以上で表示する画像 -->
  <source srcset="画像2URL" media="(min-width: △△px)" /><!-- △△px以上で表示する画像 -->
  <img src="画像3のURL" alt="サンプル画像"/><!-- それ以外の場合に表示する画像 -->
</picture>

👆このように書くことで、画面幅に応じて、別の画像が表示されます。<source>は、条件分岐に必要な数だけ増やしましょう。画像は必要になったときに読み込まれるため、パフォーマンス上の心配は不要です。

レスポンシブ画像のデモ

画像ごとにスタイルを変える

それぞれの画像ごとに、表示幅(width)や装飾を変えたい場合には、CSS側で合わせてメディアクエリを指定すればOKです。

CSS 画像ごとに幅などのスタイルを変える
.sample img {
  max-width: 100%;
  width: 200px;
}

/* 画面幅が800px以上のとき */
@media only screen and (min-width: 800px) {
  .sample img {
    width: 400px;
  }
}

/* 画面幅が1200px以上のとき */
@media only screen and (min-width: 1200px) {
  .sample img {
    width: 600px;
    border: solid 3px bold; /* 例:1200px以上でのみ線で囲む */
  }
}

👆<source>の画像であっても、img { ~ }という書き方でスタイルを適用できます。逆にsource { ~ }というように<source>自体にCSSを適用しようとしても、うまく効きません。

🤔
CSSで画像を切り替えてはダメ?

CSSのdisplay: noneとメディアクエリを使えば、画面幅に応じて別画像に切り替えることができます。「特定の幅以上だったら画像Aを表示して、画像Bを非表示にする」というような手法ですね。

この方法だとHTMLやCSSが見づらくなるだけでなく、画面幅にかかわらず、どちらの画像も読み込まれてしまうため、パフォーマンス上の問題があります(display: noneは画面上で隠すだけなので、画像自体は読み込まれてしまいます)。

<picture>でレスポンシブに画像を切り替える方法なら、必要になった画像しか読み込まれません。

対応ブラウザでのみWebP画像を表示するサンプル

HTML
<picture>
  <source srcset="WebP画像のURL" type="image/webp"/>
  <img src="WebP未対応のときに表示する画像のURL" />
<picture>

👆WebP画像をページに貼りたい場合は、このように書きましょう。<img>に「WebP未対応だった場合用の画像」を指定しておくわけですね。

なお、<source>のWebP画像が表示される場合も、適用されるCSSは<img>に対するCSSと変わりません。つまり、表示される画像のスタイルは同じです。WebP画像用に別途CSSを指定する必要はありません。

関連リンク

ブラウザ対応状況

🖥デスクトップ

  • Chromeのアイコン
    Chrome
    38〜
  • Safariのアイコン
    Safari
    9.1〜
  • Firefoxのアイコン
    Firefox
    38〜
  • Edgeのアイコン
    Edge
    13〜
  • IEのアイコン
    IE
    未対応

📱モバイル

  • Android Chromeのアイコン
    Android Chrome
    108〜
  • iOS Safariのアイコン
    iOS Safari
    9.3〜

caniuse.comで詳しく見る