picture要素の関連仕様って今どうなってるんだっけ?を調べたメモ
Posted: Updated:
<picture> どうなった
勤め先がモバイルに注力していたこともあり、レスポンシブもへったくれもない世界を生きてきた。そのせいで、その類の情報にかなり疎くなっていたので、現状を軽く調査してみた次第。
HTMLでの画像リソース読み込み分岐の必要性
CSS には Media Queries があるので、Viewport の width であったりデバイスのピクセル密度であったりを条件にして background
プロパティの指定をすれば対応できる。
反面、<img>
要素と src
属性にはそのような仕組みがないため、Media Queries で可能な条件で同じようにやろうと思うと、JavaScript で DOMContentLoaded
のあとに"頑張って"操作するか、バックエンドで UserAgent に応じて"賢く"返す仕組みを用意しなければならない。
WebP のような画像形式にせよ、解像度レパートリーにせよ「最適」を突き詰めたとき、画像リソースの配信は複雑化と断片化が進む一方なのが現状だ。それを解決するのが <picture>
関連仕様ということになる。
現在の仕様
だいぶ前に <picture>
要素の関連仕様の話がではじめたころはまとまってない印象だったが、少なくとも制作者側にとっての仕様(インターフェース)は固まりつつある様子。
<picture>
関連仕様ということでまとめているが、後述するように <img>
も srcset
や sizes
といった新しい属性を指定できるようになり仕様面で強化されている。
HTML 5.1 Nightly に入ったっぽい
ずっとWHATWGのほうで更新されていた印象だったが、W3Cの HTML 5.1 Nightly のほうにもThe picture elementが追加されていた。
今回はWHATWGのHTML Standard - The Picture elementからサンプルを引用しつつ、この記事を書いている時点での仕様を紹介する。
要素は <picture> と <source>
<picture>
は、0または1以上の <source>
を内包し、そのあとに1つの <img>
を持つ。次の例では、<source>
の media
を条件として適合すれば srcset
の値が <img>
の src
として扱われる。
<picture>
自体は <source>
と <img>
を結びつけるラッパー要素のような位置づけだ。<video>
のことを思い出すと近いイメージで理解できるだろう。
属性は srcset と sizes と media
<picture>
関連要素は、それぞれ次のような属性をもつことができる。
<picture>
: 特になし<source>
:media
・sizes
・srcset
・type
<img>
:src
・sizes
・srcset
・alt
そしてこれらの属性の掛け合わせが鬼のように複雑だ。条件を指定したら画像とHTMLを書き出してくれるPhotoshopプラグインが流行りそうなくらいには面倒くささを感じる。
主要な分岐条件
ここまでの例でもすでに登場しているが、主要な条件として次の4種類がある。
- Viewportのサイズ(viewport)
- デバイスピクセル比(device pixel ratio)
- 画像の形式(image format)
- Art Direction(art direction)
これらの条件を、前述した要素・属性を組み合わせて駆使することで、状況に応じて最適な画像を読み込むための指定をおこなうことができる。
Viewportのサイズ(viewport)を条件にする
Viewport-based selectionとして仕様書に載っている。srcset
と sizes
を指定して条件を記述する。
次の例では sizes
がメディアクエリを使った条件で、その結果 srcset
属性から適切なリソースが選ばれる。sizes
の vw
というのはViewport Widthの略らしい。CSSピクセルとかじゃなくて%の扱い。
- max-width:30emが真なら、Viewportの100%に近い画像をsrcsetから選ぶ
- max-width:50emが真なら、Viewportの50%に近い画像をsrcsetから選ぶ
- それ以外はViewportの33%から100px引いた値に近い画像をsrcsetから選ぶ
srcset
の画像ファイル名の後ろのスペースをあけて 200w
と書いてあるのは、その画像にリクエストしなくてもそのリソースがどの程度のwidthをもっているリソースなのかを判別材料にするためだろう。
デバイスピクセル比(device pixel ratio)を条件にする
Device-pixel-ratio-based selectionとして仕様書に載っている。<img>
に src
と srcset
を指定して条件を記述する。次の例では、デフォルト画像のほかに srcset
でピクセル密度が 1.5x
のときと 2x
のときに使う画像を指定している。
前述の sizes
もViewport-baseの説明を見る限り、pixel densityをよしなに計算して判定してくれるっぽい。
画像の形式(image format)を条件にする
Image format-based selectionとして仕様書に載っている。<source>
に type
を指定して条件を記述する。次の例ではJPGをデフォルトとして、対応していればWebPを読み込むように指定している。
Art Direction(art direction)を条件にする
Art direction-based selectionとして仕様書に載っている。<picture>
と <soucrce>
それに media
を指定して条件を記述する。次の例では、min-width: 45em
と min-width: 32em
をそれぞれブレークポイントとして、いずれか適切な画像が読み込まれるように指定している。
Art Directionだけ適切な訳語がわからなかったのでそのままで書いているが、これもメディアクエリを使えると思えばおそらく問題ない。(orientation:portrait)
のような指定もできる。
条件を組み合わせる
これらの条件はもちろん複合条件として扱うことができる。
ここではそれらのサンプルを割愛するが、Responsive Images: Use Cases and Documented Code Snippets to Get You Startedに網羅的なパターンのサンプルが紹介されている。ここまで説明した内容を踏まえれば、見れば分かるはずなので、より詳しく知りたい人はご覧いただきたい。
対応状況
<picture>
関連仕様のブラウザ対応はやはりChromiumが先行気味だ。つい先日に公開された次の記事ではChrome 38 Betaで <picture>
要素をサポートしたことを記事冒頭で紹介している。Betaにきたということは、Stableまであと一歩ということでわりと近未来の話だ。
まさかのクラウドファウンディングで実現
This release adds support for the new
Yoav Weiss氏がクラウドファウンディングで資金を募って、これらの実装に貢献したらしい。いや、なんかクラウドファウンディングって凄いね。。。
Chrome, Firefox, Opera の開発版は対応済み
Picturefill 2.0: Use the picture element todayや、Can I use - picture elementを読むと分かるが、Chromium が先行気味なだけで、Firefox や Opera の Nightly Build でもすでにサポートされている。
その他ブラウザとPolyfill
WebKitには srcset
属性は実装済みのようだったので調べてみたところ、前述の Blink に関連実装をしたYoav Weiss氏のブログで、いくつかのブラウザについて言及されていた。中でも WebKit については、Safari 8 には入っていないものの <picture>
要素の対応を進めているようだ。
しばらくの間、Internet Explorer や Safari, iOS Safari, Android Browser の類は、<picture>
や srcset
のPolyfillであるPicturefillを利用すれば良いかもしれない。
この Polyfill は Filament Group が開発していて Browser Support を見る限り、IE9やAndroid 2.3で若干の制約はあるようだが大体使える感じっぽい。(実際に運用したことはないので悪しからず)
まとめ
ひと通りすっきりした。
- Chrome, Firefox, Opera はそのうち対応がくる
- Safari, iOS Safari はさらにそのあと対応がきそう
- Internet Explorer, Android Browser はよくわからない(AndroidはよChromeになれ)
- 制作側にとっての仕様は固まってきている
- 条件覚えるのはともかく、手書きするのつらそう
- ツール作ったらワンチャンあるでこれ
- Yoav Weiss氏がんばれ、超がんばれ
ここまで書いて気づいたのだが、本当に知りたかったのはResponsive imagesのための-webkit-image-set()で知った image-set()
の行方だった気がしてきた。
ウロ覚えこわい。
参考URL
- Chromium Blog: Chrome 34 Beta: Responsive Images and Unprefixed Web Audio
- HTML Standard - The Picture element
- Picture element implementation in Blink | Indiegogo
- Chromium Blog: Chrome 38 Beta: New primitives for the next-generation web
- Dev.Opera — Native Responsive Images
- Picturefill 2.0: Use the picture element today | Filament Group, Inc., Boston, MA
- Testing Responsive Images ∙ An A List Apart Blog Post
- Dev.Opera — Responsive Images: Use Cases and Documented Code Snippets to Get You Started
- Surfin' Safari - Blog Archive » Improved support for high-resolution displays with the srcset image attribute
- WebKit Has Implemented srcset, And It's A Good Thing | Smashing Magazine