画像のレスポンシブ対応には、これまでずっとベストな解決策と言えるものはありませんでした。
しかし、ようやくレスポンシブサイトにおける画像最適化の問題に決着がつきそうです。
それが、picture要素によるレスポンシブイメージの実装です。
複雑なスクリプトを使うことなく、HTMLだけで画像を切り替えられる picture 要素の書き方と実践的な使い方を紹介します。
picture の使い方を理解するには、あらかじめ srcset 属性の書き方・使い方についての知識があると理解しやすいです。srcset についての解説もご覧ください。
目次
picture要素とは
picture要素は、HTML5.1で追加されたタグです。
pictureは要素単体では動作せず、source と img の要素を子要素に持つことで機能する入れ物要素です。
複数の画像リソースの中から、 ブラウザの状況に応じて希望する画像を1つ表示してくれます。
画像リソースを複数記述しても、表示条件にマッチする画像1枚のみが読み込まれるため、他の候補画像を無駄にロードすることはありません。
対応ブラウザ
picture要素は多くのブラウザが対応していますが、IE (Internet Explorer) が対応していません。
pictureに未対応のブラウザでも img 要素として読み込まれるので、画像が表示できないということはありません。
IEでも picture に対応させるには、picturefill という JavaScript を利用します。
picturefillを導入すれば srcset と sizes 属性も使えるようになります。
picture と srcset の違い
pictureを使った画像の切り替えと img srcset は似ていますが、pictureの方がより柔軟な対応ができます。
pictureが子要素に持つ source タグは srcset 属性を持つため、組み合わせて利用することができます。
サイズ(解像度)違いの複製画像をデバイス環境に応じて切り替えるだけなら img srcset の利用で充分ですが、それ以上の対応が必要な場合は picture を利用します。
具体的には、ブラウザによって読み込む画像フォーマットを変更したり、単なるサイズ違いに留まらない画像の切り替えを行いたい時です。(※後述)
picture の書き方
先述のとおり、要素そのものは容器の役割なので、内包する子要素に画像の記述をすると機能します。
pictureは、0個以上の source タグと1つの img タグを内包させなくてはなりません。
sourceは、メディアのリソースを読み込むためのタグで、picture の他に audio や video 要素の子要素として使われる要素です。
img要素の記述は必須で、sourceに記述した適用条件に合致しない状況で読み込まれたり、picture に未対応のブラウザ環境で使われます。
<picture>
<source media="メディアクエリ" type="MIMEタイプ" srcset="…">
… 必要な分 source を記述 …
<img src="…">
</picture>
複数の source は、上に(先に)書いたものから順に条件判定を行い、マッチしたリソースが見つかればそれを読み込むため、記述する順番に意味があります。
source タグ内では srcset 属性は使えますが、src属性は使えません。
media属性には、メディアクエリを指定します。
type 属性には、画像ファイルの種類(MIMEタイプ)を記述します。
JPEGは image/jpeg
、PNGは image/png
、GIFは image/gif
、SVGなら image/svg+xml
です。
type と media 属性は省略可能です。
sizes属性も利用できます。
続いて、具体的な使い方を見ていきましょう。
アートディレクション
アートディレクションとは、デバイスの環境に応じて「内容の異なる画像」を表示させるようにすることです。
「内容の異なる画像」とは、クリッピング(トリミング)や縦横比の変更をするなど、単なる複製ではない画像のことです。
例えば、PC用の画像をそのまま縮小してもスマートフォンでは見づらいことがありますし、逆のケースもまたしかりですよね。
アートディレクションを行えば、デバイス環境に合った最適な魅せ方で演出することができます。
<picture>
<source media="(min-width: 960px)" srcset="img-pc.jpg">
<source media="(min-width: 640px)" srcset="img-tablet.jpg">
<img src="img-sp.jpg">
</picture>
上記コードサンプルは、幅960px以上でPC用画像、640px以上でタブレット用画像、639px以下はスマートフォン用画像を表示します。
画像フォーマットの選択
保存形式が異なる画像も1つの picture 内にセットすることができます。
例えば、WebP形式の画像とJPEG形式を切り替えるといった利用方法です。
WebPは画質と圧縮率に優れた高性能な画像フォーマットですが、現状でAndroid, Chrome, Operaのブラウザしか対応していないため、これからの普及を期待したいところです。
ですので、WebPに対応しているブラウザにはWebPを読み込ませ、未対応ならJPEG画像を読みこませる、と言うように指定します。
<picture>
<source type="image/webp" srcset="img-advanced.webp">
<img src="img-standard.jpg">
</picture>
画像形式を切り替えるには、type属性を利用します。
sourceで type="image/webp"
を指定し、WebPに対応していないブラウザでは img タグが読み込まれます。
これだけで、WebPとJPEGのフォーマットを自動的に選択してくれます。
参考: WebP – Wikipedia
srcset や sizes による切り替えとの組み合わせ
srcset と sizes 属性による画像切り替えを組み合わせれば、実践的なレスポンシブイメージを実装できます。
アートディレクション & 高解像度対応
<picture>
<source media="(min-width: 960px)" srcset="img-pc-3x.jpg 3x, img-pc-2x.jpg 2x, img-pc-1x.jpg 1x">
<img srcset="img-mobile-3x.jpg 3x, img-mobile-2x.jpg 2x" src="img-mobile-1x.jpg">
</picture>
srcsetでピクセル密度の記述子 x
を用いて、端末のデバイスピクセル比に応じた解像度の画像を読み込みます。
PC用とモバイル用でそれぞれ解像度のバリエーションを用意しておきます。
アートディレクション & 表示サイズ変更
<picture>
<source media="(min-width: 960px)" sizes="50vw" srcset="img-pc-1920.jpg 1920w, img-pc-1440.jpg 1440w, img-pc-960.jpg 960w, img-pc-480.jpg 480w">
<img sizes="(min-width: 480px) 75vw, 100vw" srcset="img-mobile-1440.jpg 1440w, img-mobile-1280.jpg 1280w, img-mobile-960.jpg 960w, img-mobile-640.jpg 640w, img-mobile-480.jpg 480w, img-mobile-320.jpg 320w" src="img-mobile-480.jpg">
</picture>
- 960px以上の場合はビューポート幅の50%の長さでPC用画像を表示
- 480 ~ 959pxではビューポート幅の75%の長さでモバイル画像を表示
- 479px以下の時は横幅いっぱいにモバイル用画像を表示
幅記述子 w
の srcset と sizes 属性を利用して、ビューポート幅(ブラウザ表示幅)に応じた画像の表示サイズを変更しています。
端末のデバイスピクセル比も計算した上で適切なサイズの画像が読み込まれます。
アートディレクション & 表示サイズ変更 & フォーマット選択
さらに、WebPフォーマットに対応させるコードも加えると次のようになります。
<picture>
<source type="image/webp" media="(min-width: 960px)" sizes="50vw" srcset="img-pc-1920.webp 1920w, img-pc-1440.webp 1440w, img-pc-1280.webp 1280w, img-pc-960.webp 960w, img-pc-640.webp 640w, img-pc-480.webp 480w">
<source type="image/webp" sizes="(min-width: 480px) 75vw, 100vw" srcset="img-mobile-1440.webp 1440w, img-mobile-1280.webp 1280w, img-mobile-960.webp 960w, img-mobile-640.webp 640w, img-mobile-480.webp 480, img-mobile-320.webp 320w">
<source media="(min-width: 960px)" sizes="50vw" srcset="img-pc-1920.jpg 1920w, img-pc-1440.jpg 1440w, img-pc-1280.jpg 1280w, img-pc-960.jpg 960w, img-pc-640.jpg 640w, img-pc-480.jpg 480w">
<img sizes="(min-width: 640px) 75vw, 100vw" srcset="img-mobile-1440.jpg 1440w, img-mobile-1280.jpg 1280w, img-mobile-960.jpg 960w, img-mobile-640.jpg 640w, img-mobile-480.jpg 480w, img-mobile-320.jpg 320w" src="default-img.jpg" >
</picture>
補足ですが、1つ目の <source>
の media="(min-width: 960px)" sizes="50vw"
は sizes="(min-width: 960px) 50vw"
と書き換えることもできます。
これは source タグで media 属性が使えるためです。
つまり、二通りの書き方ができます。
しかし img タグは media 属性を使えないので、sizes="(メディアクエリ) 幅長"
の形式で書く必要があります。
pictureのメリット
picture要素を使えば、img srcset の機能組み合わせて自由にレスポンシブイメージを実現できることがおわかりいただけたと思います。
特にアートディレクションのような別画像への切り替えは、以前からレスポンシブサイトではよく使われている手法だったので、JavaScriptを書かずにHTMLだけで記述できるのはとても便利です。
ブラウザの標準機能なので、読み込みやレンダリングのパフォーマンスも向上するので、ユーザーにも運営(制作)側にもメリットの多い機能です。
コメントをどうぞ