レスポンシブで画像を表示するにはどうすればよいか調べてみた

スマートフォン、タブレット、PCでレスポンシブなWebサイトをコーディングする際に、画像もレスポンシブにする必要がある場合、どういった要素を使って、どのように画像を切り分けるか悩みます。そこで自分なりに調べてみました。

img要素のsrcsetとsizes属性を使う

コードの全体は下記のようになります。

<img srcset="images/small.jpg 320w,images/medium.jpg 640w,images/large.jpg 1280w" src="images/large.jpg" sizes="(max-width:1280px) 100vw, 1280px">

上記のようにすると、ブラウザが自動で各画面サイズで、記述した画像を選択してレスポンシブで表示してくれます。

ブラウザが自動で画面サイズごとに各画像を選択してレスポンシブで表示

srcset属性について

画像ファイルのパスと横幅はsrcset属性に記述します。

srcset="images/small.jpg 320w,images/medium.jpg 640w,images/large.jpg 1280w"

横幅の単位はwを使います。small.jpgは320px、medium.jpgは640px、large.jpgは1280pxの画像を使っています。ブラウザの幅が320wの時に「small.jpg」を、640wの時に「medium」を、1280wの時に「large.jpg」の画像が自動で表示されます。

sizes属性について

画像の横幅はsizes属性に記述します。「(max-width:1280px) 100vw」で画面が1280px以下の時は画像を画面幅いっぱいに、それ以外では1280pxで画像を表示します。

sizes="(max-width:1280px) 100vw, 1280px"

vwはビューポートの幅に対する割合で、100vwはビューポート幅に対して100%(画面幅いっぱい)となります。

Safariブラウザ

Safariブラウザの場合、通常は下記のように縦(ポートレイト)と横(ランドスケープ)の切り替え時に画像を再読み込みしてくれません。動画はiOSのSafariブラウザのものです。

Safariブラウザで縦と横を切り替えたときに画像を画面の横幅いっぱいにする場合は、CSSでimgに対して「width: 100%;」を指定します。

img {
  width: 100%;
}

画面を縦、横と切り替えても画像が画面の横幅いっぱいになっていることがわかります。

img要素のsrcsetとsizes属性は同じ画像をレスポンシブ表示したい場合に向いてると言えます。srcsetとsizes属性の対応状況は下記のページで確認することができます。

srcsetとsizes属性の対応状況

picture要素を使う

次はpicture要素を使ってレスポンシブで画像を表示してみます。コードの全体は下記のようになります。

<picture>
    <source media="(max-width:400px)" srcset="images/pic-320.jpg 400w" sizes="100vw">
    <source media="(max-width:600px)" srcset="images/pic-640.jpg 600w" sizes="100vw">
    <img src="images/pic-1280.jpg">
</picture>

上記のようにするとレスポンシブで画像が表示されます。ブラウザの幅が400px以下の時に「pic-320.jpg」を画面幅いっぱいに表示、400px以下の時に「pic-640.jpg」を表示、それ以外の時に「pic-1280.jpg」を表示します。

picture要素で画像をレスポンシブ表示

また、picture要素で画像を表示すると、sourceタグで指定したメディアクエリによって表示する画像そのものを変えているので、CSSでimgに100%の指定をしていない場合でも、Safariブラウザで横に切り替えた場合に画像を再読み込みさせて画面幅いっぱいすることができます。

画面を横にしたときに画像が画面幅いっぱいになっていることがわかります。

違う画像を表示してみる

今度は違うサイズの違う画像を切り替えて表示してみます。全体のコードは下記のようになります。

<picture>
    <source media="(max-width:400px)" srcset="images/sp.jpg 400w" sizes="100vw">
    <source media="(max-width:600px)" srcset="images/tab.jpg 600w" sizes="100vw">
    <img src="images/pc.jpg">
</picture>

上記のようにすると、ブラウザの幅が400px以下の時に「sp.jpg」を画面幅いっぱいに、400px以下の時に「tab.jpg」を画面幅いっぱいに、それ以外の時に「pc.jpg」を表示します。

画面幅ごとに違うサイズの違う画像を表示

アートディレクションを行ってみる

picture要素は画像そのものを切り替えることができるので、スマホなどの画面幅が小さい時に、アートディレクション(トリミング)を行って重要な部分を表示させることができます。特に難しいことはなく、指定したサイズの時にトリミングした画像を表示させるだけです。わかりやすくするために同じ画像を例にします。コードは下記のようになります。

<picture>
    <source media="(max-width:320px)" srcset="images/film-triming.jpg 640w" sizes="100vw">
    <source srcset="images/film-medium.jpg 640w,images/film-large.jpg 1280w" sizes="(max-width:1280px) 100vw,1280px">
    <img src="images/film-large.jpg">
</picture>

上記はpicture要素とimg要素のsrcset、sizes属性を組み合わせています。

メディアクエリで指定された画面サイズ時にトリミングされた画像が表示

一番小さい画面サイズ(max-width:320px)の時に、トリミングされた画像が表示されていることがわかります。picture要素は画面幅ごとに画像を切り替える場合に向いていると言えます。

picture要素の対応状況は下記のページで確認することができます。

picture要素の対応状況

まとめ

img要素のsrcset、sizes属性とpicture要素はどちらも画像をレスポンシブで表示することはできますが、得意な部分はそれぞれ違うようです。

結論としては、同じ画像をレスポンシブ表示したい場合はimg要素のsrcsetとsizes属性を利用し、画像そのものを切り替えたい場合はpicture要素を使う、といった使い分けがオーソドックスな気がします。

また、「アートディレクションを行ってみる」で記述したように、picture要素とimg、srcset、sizes属性を組み合わせることもできるようなので、選択の幅が一気に広がると思います。

新ためて検証してみたのですが、画像表示は奥が深いと思いました。

スポンサーリンク