pictureタグで画面幅や画像形式に合わせて表示する画像を切り替える

レスポンシブサイトを作成するときには、スマホでは画像を縦長に、PCでは横長の画像を見せたいといったように、画面サイズによって画像そのものを変更したいことがあります。そんなときに使えるのがpicture タグです。

pictureタグとは

pictureタグは、条件に合わせて表示する画像を切り替えるためのHTMLタグです。条件を設定し、その条件にあった画像を表示します。

画面サイズによって、トリミングや構図の違う画像を出し分ける(アートディレクション)、AVIFやWebPなど、ブラウザが対応している画像フォーマットを出し分けるときなどに使用します。

CSSの display: none で画像を出し分ける方法と違い、pictureタグでは選ばれた画像しか読み込まれません。使わない画像までダウンロードしてしまうことがないので、表示速度の面でも有利です。

中に複数の<source>タグと1つの<img>タグを書き、ブラウザは条件に合った画像を1つだけ選んで表示します。

同じ画像のサイズ違いを出し分けたいだけなら、pictureタグを使わなくてもimgタグのsrcset・sizes属性で対応できます。

pictureタグの基本的な書き方

広告

pictureタグの中に、sourceタグとimgタグを記述します。書くときのポイントは次の3つです。

  • <source> には、表示する画像を srcset属性で指定する(srcではない)
  • <img> は必ず書き、すべての <source> の後ろに置く
  • alt属性は <img> にだけ書く
HTML
<picture>
  <source srcset="image_sp.jpg" media="(max-width: 640px)">
  <img src="image_pc.jpg" alt="商品の写真" width="1200" height="600">
</picture>

この場合、画面幅が640px以下のときはimage_sp.jpg、それ以外のときは<img>に書いたimage_pc.jpgが表示されます。

<source> で指定する主な属性は以下のものです。

  • srcset属性(リソース(画像の場所)を指定)
  • media属性(メディアクエリの指定)
  • type属性(画像フォーマットの指定)

imgタグは必須で、最後に書く

pictureタグ自体は画像を表示するものではなく、実際に画像を表示しているのは中の <img> で、<source> は「条件に合ったらimgタグの画像を表示してね」という候補の指定です。

広告

pictureタグ内の記載順通りに読み込まれ、sourceタグで指定する画像がなかったらimgタグの画像が適用されます。

そのため、<img> がないと何も表示されません。pictureタグに設定した画像が表示されないときは、まず <img> が含まれているかを確認しましょう。

<img> はどの <source> の条件にも当てはまらなかったときのフォールバック画像にもなります。sourceタグの後に、いちばん標準的な画像を指定しておきます。

imgタグの後にsourceタグがあっても無視されてしまうので最後に書くようクセ付けてしまいましょう。

altはすべての画像に合う内容にする

alt属性は<img>にしか書けません。そのためどの画像が表示されても同じ代替テキストが使われます。スマホ用とPC用でトリミングが違う場合も、どちらの画像にも当てはまる説明にしておきます。

記述順序に注意、sourceタグは上から順に判定される

ブラウザは <source> を上から順番に確認し、条件に合うものが見つかった時点でその画像を使用します。それより下のは無視されるので、書く順番が大切です。

思った通りの表示にならない場合、 <source> の記述順序の見直しが必要かもしれません。

例えば640pxの画面サイズまではスマホ用画像、960pxまではタブレット用、それ以降はPC用の画像を作成してそれぞれ表示を切り替えたい場合に以下の記述をしたとします。

HTML
<picture>
  <source srcset="image_tab.jpg" media="(max-width: 960px)">
  <source srcset="image_sp.jpg" media="(max-width: 640px)">
  <img src="image_pc.jpg" alt="商品の写真" width="1200" height="600">
</picture>

上記の順序の場合、 media="(max-width: 960px)" が先に適用されるため、media="(max-width: 640px)" まで読み込まれることはありません。そのためスマホ用の画像である image_sp.png が表示されることはありません。      

上記コードの表示

ブラウザの画面幅を拡大・縮小させると画像が切り替わります。

640px以下でも image_sp.png は表示されません。

max-widthで指定するときは数字の小さい順、min-width のときは数字の大きい順に書きます。

HTML
<picture>
  <source srcset="image_sp.jpg" media="(max-width: 640px)">
  <source srcset="image_tab.jpg" media="(max-width: 960px)">
  <img src="image_pc.jpg">
</picture>

上記コードの表示

ブラウザの画面幅を拡大・縮小させると画像が切り替わります。640px以下の画面幅で見ると、一つ前のコードとは別の画像が表示されていると思います。

media属性で画面幅によって画像を切り替える

<source> の media属性で画面サイズによって画像を出し分けることができます。CSSのメディアクエリのように min-width や max-width を使って条件を指定します。

HTML
<picture>
  <source srcset="image-sp.jpg" media="(max-width: 640px)" width="750" height="1000">
  <img src="image-pc.jpg" alt="桜のイメージ" width="1200" height="600">
</picture>

media 属性の条件は、ブラウザに対する「命令」として扱われます。条件に合う <source> があれば、ブラウザは必ずその画像を使います。
この点が、ブラウザが画像を選ぶときの「目安」でしかないimgタグの srcset・sizes 属性との大きな違いです。

上記コードの表示

ブラウザの画面幅を拡大・縮小させると画像が切り替わります。

桜のイメージ

sourceタグにもwidthとheightを書く

上の例のように、<source>ごとに画像の縦横比が違う場合は、<source>にもwidth属性とheight属性を書いておきます。

このサイズを書いておくと、画像が読み込まれる前からブラウザが表示する場所を確保できるので、読み込み後にレイアウトがずれるのを防げます。<source>に指定がない場合は<img>の縦横比率が使われるので、縦横比が違う画像では正しい場所を確保できません。

type属性で画像形式を切り替える

<source> のtype属性に画像形式(MIMEタイプ)を指定すると、ブラウザが対応している形式の画像だけを読み込ませることができます。

例えばwebp画像に対応しているブラウザならwebp、対応していなければその他の画像を表示する。といった場合に使います。ブラウザは上から順に確認し、対応している形式が見つかったらその画像を読み込みます。対応していない形式はダウンロードする前に飛ばしてくれるので、無駄な読み込みは起きません。

HTML
<picture>
  <source srcset="sample_beach.avif" type="image/avif">
  <source srcset="sample_beach.webp" type="image/webp">
  <img src="sample_beach.jpg" alt="海辺の写真" width="1200" height="800">
</picture>

上記コードの表示

海辺の写真

jpg, png, gif などは元々全ブラウザで対応しており、主にwebp表示に使われていました。現在最新バージョンのブラウザではwebpも大体対応できているので必ずしもつける必要はないと思いますが、サイト表示の対応範囲によって設定していきましょう。

ファイルサイズを小さくしやすい順に、AVIF → WebP → JPEG(またはPNG)と並べるのが一般的です。現在の主要なブラウザはAVIFとWebPのどちらにも対応していますが、<img>にJPEGやPNGを指定しておけば、万が一対応していない環境でも画像は表示されます。

画面の解像度に合わせて画像を切り替える

現在では高解像度のディスプレイも多くなり、あるディスプレイでは問題ない場合も解像度の高いディスプレイではぼやけてしまう場合もあるので、それに合わせた画像を表示させる必要があります。

設定した画像で荒れてしまう場合は大きめの画像を用意して、srcset属性に解像度に応じた値を設定します。

srcset属性の画像パスの後ろに1xや2xを付けると、画面の解像度に合わせて画像が選ばれます。
「○x」は端末のデバイスピクセル比に応じた画像を読み込ませるためのものです。

HTML
<picture>
  <source srcset="sample_sakura-sp.jpg 1x, sample_sakura-sp@2x.jpg 2x" media="(max-width: 640px)">
  <img src="sample_sakura-pc.jpg" srcset="sample_sakura-pc.jpg 1x, sample_sakura-pc@2x.jpg 2x" alt="桜のイメージ" width="1200" height="600">
</picture>

上記コードの表示

桜のイメージ

不必要なまでに高解像度の画像を設定するというのは、画像の最適化という点において正しいとは言えません。うまく活用していきましょう。

画像の幅をwで指定し、sizes属性と組み合わせる書き方も<source>で使えます。

HTML
<picture>
  <source
    srcset="sample_sakura-sp-750.jpg 750w, sample_sakura-sp-1125.jpg 1125w"
    sizes="100vw"
    media="(max-width: 640px)">
  <img src="sample_sakura-pc.jpg" alt="桜のイメージ" width="1200" height="600">
</picture>

上記コードの表示

桜のイメージ

750wのwは画面幅ではなく、画像ファイルそのものの幅(750px)を表します。xとwの違いやsizes属性の書き方は「imgタグのsrcset・sizes属性で画面に合ったサイズの画像を表示する方法」で詳しく紹介しています。

pictureタグで画像が切り替わらない!

imgタグが入っているか

picturetタグを書いているのに表示されない場合は、まずimgタグが含まれているか確認してください。

pictureタグというのはimgタグを制御するためのもので、pictureタグもsourceタグも何かを表示させる働きはありません。そのため、imgタグの記述は必須です。

sourceタグの順番が合っているか

sourceタグを上から順に確認し、表示できる画像が見つかった時点でその画像を表示、それ以降に書かれているものは無視されます。
またpictureタグをサポートしていないブラウザはimgタグの画像が表示されます。

画像は表示されるものの、思い通りの画像ではない場合は記述順序を見直してみてください。上から順に読み込み当てはまったものが適用されるため、それぞれ適用させたい画面で切り替わるように調整しましょう。
「記述順序に注意」へ

どの画像が使われているかは、ブラウザのデベロッパーツールで確認できます。「要素」パネルで<img>を選択した状態でコンソールに$0.currentSrcと入力すると、実際に表示されている画像のURLが表示されます。「ネットワーク」タブで、どの画像ファイルがダウンロードされたかを見るのもわかりやすい方法です。

デベロッパーツールの要素パネル
デベロッパーツールのコンソールパネルで $0.currentSrc を入力

キャッシュの影響

media属性で切り替えている画像は、条件が変われば切り替わります。一方で、1x・2xやwで指定したsrcsetの中からどれを選ぶかはブラウザの判断にまかされているので、すでに大きい画像をキャッシュしていると、小さい画面にしても大きい画像がそのまま使われることがあります。

確認するときはこのブラウザの違いも覚えておきましょう。

  • Chrome
    一番大きなサイズの画像ファイルをキャッシュしたら、それ以下の小さい画像は読み込まれない。
  • Firefox
    画面サイズが変わるたびに最適な画像を読み込む。
  • Safari
    最初に開いた画面サイズの画像をキャッシュし、画面サイズが変わってもその画像以外読み込まない。

画面幅を変えながら確認するときは、デベロッパーツールで「キャッシュを無効にする」にチェックを入れるか、シークレットウィンドウで確認すると、正しく判定されているかがわかりやすくなります。

pictureタグへのCSSの指定

pictureタグは<span>と同じインライン要素として扱われます。display: blockなどのCSSは効きますが、pictureタグにwidthを指定しても中の画像のサイズは変わりません。画像の大きさや角丸などの見た目は<img>に指定します。

上記コードの表示

pictureタグに「width: 100px」を設定

imgタグに「width: 100px」を設定

<img>にwidth・height属性を書いている場合、CSSでwidth: 100%だけを指定すると画像が縦に伸びてしまうので、height: autoもあわせて指定しておきます。

CSS
picture img {
  display: block;
  width: 100%;
  height: auto;
}

pictureタグとimgタグのsrcsetの使い分け

画像の表示切り替えはpictureタグでもimgタグでもできます。レスポンシブで切り替えたい画像によって、pictureタグとimgタグを使い分けます。

画像をレスポンシブ対応する場合というのは、以下のことが考えられます。どちらを使うかは、「画像の見た目を変えたいか」で判断します。

やりたいこと使うもの
同じ画像のサイズ違いを、画面幅や解像度に合わせて出し分けたいimgタグのsrcset・sizes
スマホとPCでトリミングや構図の違う画像を見せたいpictureタグ(media属性)
AVIFやWebPに対応したブラウザにだけ軽い画像を読み込ませたいpictureタグ(type属性)

imgタグのsrcsetは、どの画像を使うかをブラウザが通信環境やキャッシュも考えて選んでくれるので、画像の見た目を変えないならこちらのほうがシンプルです。画像の内容を変えたい場合や、形式を出し分けたい場合にpictureタグを使いましょう。

広告

カテゴリー : HTML-CSS

タグ :