レスポンシブ・イメージがもうすぐネイティブ実装!いまから使える?ポリフィル「Picturefill 2.x」を検証

Advertisement

レスポンシブ・デザインの画像の扱いの課題を解決するのが「レスポンシブ・イメージ」です。この「レスポンシブ・イメージ」には紆余曲折あったわけですが、熱心な開発者の方々のおかげでようやく仕様がまとまり、ブラウザでのネイティブ実装も進んでいます。

結論から言うと、ブラウザのネイティブ実装はまだこれからですし、ポリフィルのPicturefill 2.xには大きな欠陥があり、プロダクションサイトでの使用は待ったほうが良いと思います。しかし、多くの開発者が多大な時間を費やして実現しようとしているレスポンシブ・イメージです。この存在が日本でもより多くの人に広まればと思い、いまの状況をまとめてみました。

追記: 2015.05.30

すでにPicturefillを使っている場合、2.3.1以降であることをご確認ください!

目次

レスポンシブ・イメージのいま

レスポンシブ・イメージの各ブラウザでの実装状況を、実装を行っている開発者の1人、YoavさんがDev.Operaの記事「Native Responsive Images(2014年8月19日)」で以下のように書いています:

  • 数週間のうちに、Chrome 38、Opera 25、Firefox 33に搭載予定
  • Webkitではsrcsetとsizesが実装済みだがSafari 8には未搭載。picture要素はこれから実装予定(Yoav Weissさんが実装中)
  • IEでは実装を「考え中(under consideration)」と公表。実装の可能性もある?

SafariとIEでの実装を残すのみということで、AppleとMicrosoftの今後の動きに注目です。Firefox 33ではRICGサイトで「behind flags」とある通り、設定の変更が必要です。

Picturefill 2.x

レスポンシブ・イメージをJavaScriptで実装するポリフィル「Picturefill 2.x」では、最新のpicutre要素の仕様に沿ったものが実装されていて、picture要素、srcset属性、sizes属性を使ってレスポンシブ・イメージを実現できます。

picture要素の仕様が固まる前から機能的には同等なことが実現できるように用意されていたPicturefill 1.xのアップデート版です。よい感じで動いてはいるものの、大きな欠陥があるので、プロダクションサイトでの使用には、もう少し検証が必要だと思います。それまではPicturefill 1.2を使うのが良さそうです。

Picturefill 2.xのブラウザ・サポートはこちらで確認できます。Dev.Operaのこの記事で推奨されているフォールバックとしてのsrc属性の記述に問題であったり、source要素使用の際の、IE9やAndroid 2.3での注意点などが書いてあるので、使用の際には必ずチェックすることをオススメします。

Chrome CanaryとFirefox Nightlyでの実装

Picturefillなしでも、Chrome CanaryFirefox Nightではレスポンシブ・イメージがネイティブで動作します。

Chrome Canaryは、ダウンロードして起動すると、そのままpicture要素やscrset属性、sizes属性が使えます。今回のデモのために作ったページは、問題なく動いてます。

Firefox Nightlyの場合は、Shift-F2でDeveloper Toolbarを表示させて以下の設定を有効にする必要があります。

pref set dom.image.srcset.enabled true
pref set dom.image.picture.enabled true

設定はアドレスバーからabout:configにアクセスすることで確認できます:

レスポンシブ・イメージで解決できる3つの課題

さて、デモを紹介する前に、レスポンシブ・イメージでいったいなにを解決したかったのか、おさらいしておきたいと思います。そもそも、なんでレスポンシブ・イメージが必要なのか?ってやつですね。

レスポンシブ・イメージで解決できる課題のなかで、一番重要なのは以下の3つです:

  1. 幅に合わせた寸法での表示
  2. 画像のアートディレクション
  3. Retina対応

1. 幅に合わせた寸法での表示

表示パフォーマンスを考慮すると、横幅が800pxのスクリーンには800pxの画像、1200pxのスクリーンには1200pxの画像を表示するといったように、それぞれの幅にあわせた画像を表示するのがベストです(厳密に言うとRendered Sizeにあわせるのがベストなんですけどね)。たとえば、1200pxの画像を300pxで表示すると、レンダリングのためにブラウザのリソースを必要とするだけでなく、ファイルサイズも必要以上に大きくなってしまいます。

2. 画像のアートディレクション

写真によっては必要ないですが、大き目のスクリーンでは全体が見える写真が良い場合でも、スマホのような小さいスクリーンでは、写真の要点にクローズアップしたものが良い場合もありますよね。

3. Retina対応

Retinaスクリーンが登場してしばらく経ちますが、綺麗な画面で画像だけがぼやけていると、かなり印象が悪くなります。Retinaスクリーン向けには、それ用の高解像度の画像を表示したいですよね。

4つ目のユースケース

HTML Living Standardにある仕様の説明やDev.Operaの記事「Responsive Images: Use Cases and Documented Code Snippets to Get You Started」では、ファイルタイプによるユースケースが紹介されていますが、個人的にはあまり重要だと思っていません(少なくとも2014年8月現在では。。。)。

Picturefill 2.xデモ①: 幅に合わせた寸法での表示

ブラウザの表示領域(Viewport)に合わせて違うサイズ(寸法)の画像を選択する方法です。HTML Living Standardの仕様では「viewport-based selection」と呼んでいます。この使い方の場合、picture要素は必要なくて、img要素にsrcset属性を使って複数のサイズの画像を記述します。

HTMLは以下のようになります:

<img
  sizes="100vw"
  srcset="img/200w.png 200w, img/400w.png 400w, img/600w.png 600w, img/800w.png 800w, img/1000w.png 1000w, img/1200w.png 1200w"
  alt="Picturefill 2.xのデモ画像">

デモはこちら

sizes属性

sizes属性で条件とそれに応じた画像表示を指定します。条件にはメディアクエリを使いますが、ここでは指定をせず、画像表示のみ「100vw」として指定しています。vw(Viewport Width)は表示領域の割合を表す数値で、100vwはViewportの100%になります。sizes属性は、デフォルトが100vwなので指定しなくてもOKです。

たとえば、sizes=”(min-width: 640px) 50vw, 100vw”とすると、640px以上ではViewportの50%に、また、それ以外の幅ではViewportの100%での表示に最適な画像を選択するよう指定しています。これは、たとえば640pxのブレイクポイントを境に、それぞれ50%幅の2カラムのレイアウトにする場合に使います。

<img
  sizes="(min-width: 1140px) 570px, (min-width: 640px) 50vw, 100vw"
  srcset="img/400w.png 400w, img/600w.png 600w, img/800w.png 800w, img/1000w.png 1000w, img/1200w.png 1200w"
  alt="幅に合わせた寸法での表示の例">

デモはこちら

※この例では、コンテンツの最大幅を1140pxに指定しているため、それ以上のスクリーンサイズでは570px(1140px ÷ 2)を指定しています。

sizes属性の指定の順番について

sizes属性では、メディアクエリが当てはまる最初の条件が適用されるため、以下の2つでは表示が異なるので注意が必要です。

sizes="(min-width: 640px) 30vw, (min-width: 1140px) 570px, 100vw"
sizes="(min-width: 1140px) 570px, (min-width: 640px) 30vw, 100vw"

注: 100vwの前のスペースのある・なしでChrome Canary(Mac / 39.0.2129.0 canary (64-bit))では挙動が異なりました。Picturefillでは同じ挙動でした。

srcset属性

画像のURLと幅を「w」で指定したものを1組みとしたものをカンマで分けたリストにして指定します。このリストとsizes属性の指定をベースに、ブラウザが状況に応じて最適な画像を選択してくれる仕組みになっています。ブラウザ側での画像選択の仕様は細かく指定されていなくて、将来的には回線速度やユーザのブラウザ設定などをもとに、ブラウザが自動でやってくれるようになるそうです(ブラウザ・ベンダー次第)。

src属性について

srcsetをサポートしないブラウザ用に、フォールバックとして記述することが推奨されています(参照)。これはデモ②、デモ③でも同様です。しかし、Picturefill 2.xではいくつかの理由により、入れないようにしたほうが良いようです。

スクリーンサイズと表示される画像

sizes属性が固定の100vwのデモだと、表示される画像は以下のようになります。

スクリーン幅 表示される画像(1x ピクセル比)
〜400px 400w.png
401px〜600px 600w.png
601px〜800px 800w.png
801px〜1000px 1000w.png
1001px〜 1200w.png

ピクセル比が1.0より大きい場合

たとえば、ピクセル比(device pixel ratio)が2.0のiPhone(4以上)やiPad(第3世代以上)、また、3.0のNexus 5のような端末だと、それら端末のスクリーンに最適な画像サイズを選択してくれます。

端末 ピクセル比 幅(CSS Pixel) 表示される画像
iPhone 5s 2.0 320px(Portrait) 800w.png
568px(Portrait) 1200w.png
iPad 2.0 768px(Portrait) 1200w.png
1024px(Portrait)
Nexus 5 3.0 360px(Portrait) 1200w.png
640px(Portrait)

Picturefill 2.xデモ②: 画像のアートディレクション

ブラウザの表示領域(Viewport)にあわせて、内容の異なる画像を選択する方法です。HTML Living Standardの仕様では、「art direction-based selection」と呼んでいます。

以下のデモでは、640px未満のスクリーンではクローズアップした写真のcat-XXXw-close.jpgのいずれか、640px以上では全体が見られる写真のcat-XXXw.jpgのいずれかが表示されるように指定しています。

HTMLは以下のようになります:

<picture>
  <source
    media="(min-width: 640px)"
    srcset="img/cat-800w.jpg 800w, img/cat-1000w.jpg 1000w, img/cat-1200w.jpg 1200w">
  <img
    srcset="img/cat-400w-close.jpg 400w, img/cat-600w-close.jpg 600w, img/cat-800w-close.jpg 800w, img/cat-1000w-close.jpg 1000w, img/cat-1200w-close.jpg 1200w"
    alt="猫の窓際">
</picture>

デモはこちら

source要素

source要素では、640px以上のスクリーンサイズで表示する画像を、srcsetを使って複数指定しています。複数指定した画像の中から、ブラウザが最適な画像を選択してくれる仕組みです。Picturefill 2.xではIE9で問題があるので、以下のようにIEコメントで囲んだ<video>タグを記述するように書かれています。

<picture>
  <!--[if IE 9]><video style="display: none;"><![endif]-->
  <source
    media="(min-width: 640px)"
    srcset="img/cat-800w.jpg 800w, img/cat-1000w.jpg 1000w, img/cat-1200w.jpg 1200w">
  <!--[if IE 9]></video><![endif]-->
  <img
    srcset="img/cat-400w-close.jpg 400w, img/cat-600w-close.jpg 600w, img/cat-800w-close.jpg 800w, img/cat-1000w-close.jpg 1000w, img/cat-1200w-close.jpg 1200w"
    alt="猫の窓際">
</picture>

img要素

ここでは640px未満のスクーンで表示する画像を、srcsetを使って指定しています。

Picturefill 2.xデモ③: Retina対応

実は、デモ①とデモ②でもRetina対応ができているのですが、Retina対応を明示的に記述したい場合は、以下のような指定も可能です。HTML Living Standardの仕様では、「device-pixel-ratio-based selection」と呼んでいます。

<img
  srcset="img/cat-400w.jpg 1.0x, img/cat-800w.jpg 1.5x, img/cat-1200w.jpg 2.0x"
  class="img-fixed-400px"
  alt="猫の窓際">

デモはこちら

x記述子

srcset属性に、1.5xや2.0xといったx記述子(descriptor)を画像URLとペアにして記述することで、それぞれのピクセル比(device-pixel-ratio)で表示したい画像を指定できます。

固定幅にするためのclass

HTML Living Standardに注意書きに、表示領域にあわせて画像を表示する場合(width: 100%にしている場合など)は、x記述子は適切ではないとあります。その場合は、デモ①のようにsrcset属性に複数の画像を指定するとこで、ブラウザが適切な画像サイズを選択してくれます。

ブラウザでの動作確認

Picturefill 2.1.0とネイティブ実装(Chrome CanaryとFirefox Nightly)での動作を比較・確認してみました。

Picturefill 2.1.0

デスクトップブラウザ

以下のブラウザでテストしてみました:

  • Mac Chrome 36.0.1985.143
  • Mac Firefox 31.0
  • Mac Safari 7.0.6 (9537.78.2)
  • IE 11.0.9600.17207
  • Win Chrome 36.0.1985.143 m
  • Win Firefox 31.0

※IE10以下でのテストをサボっててすみません。テストしたら追記します。テストされた方がいたら、ぜひ、結果をコメントでシェアいただければ幸いです!

問題・バグ?

  • 仕様で推奨されているようにフォールバックとしてsrc属性を使用して画像を指定すると、ページが読み込まれる際に、フォールバック画像が読み込まれた後にsrcsetの画像が読み込まれます。
  • これは、PicturefillのBrowser Supportによると回避策がないらしく、src属性を入れないで記述するしかないようです。
  • しかし、src属性を入れないとカラの画像の枠とaltテキストが一瞬表示されてしまいます。また、JavaScrptがオフの環境では、altテキストが表示されるのみになります。

モバイル端末

以下のモバイル端末でテストしてみたところ、デスクトップブラウザと同じようにカラの画像の枠とaltテキストが一瞬表示されます。

  • iPhone 5s iOS 7.1.2 (11D257)
  • iPad(第3世代) iOS 7.1.2 (11D257)
  • Nexus 5 Android 4.4.4 Chrome 36.0.1985.135

Chrome Canary 39.0.2130.0 canary (64-bit)

Picturefillであった問題もなく、良い感じでレスポンシブ・イメージを使ったデモページが動作しています。

Firefox Nightly 34.0a1

以下の問題がありました。たぶん、2つともバグですね。

  1. ページをリロードしないと画像が切り替わらない
  2. デモ②のsrcsetで複数指定した画像が、1つ目のものだけしか選択されない

画像のファイルサイズについて

今回の検証のために、200pxから1200pxまで、200px毎に画像を作ってみたのですが、ファイルサイズは以下になりました。ImageOptimで最適化をしたあとのファイルサイズです。

たとえば、400pxしか必要ないのに1200pxのファイルを表示していたら、ユーザに83KBも無駄にダウンロードさせることになります。1つだけならいいですが、これが複数の画像になると1MBなんてすぐにいってしまいますね。表示パフォーマンスの観点からも、レスポンシブ・イメージの実装が安定してきたら、ぜひ活用したいですね。

ファイル名 寸法 ファイルサイズ
cat-200w.jpg 200 x 120px 7 KB
cat-400w.jpg 400 x 240px 17 KB
cat-600w.jpg 600 x 360px 32 KB
cat-800w.jpg 800 x 480px 50 KB
cat-1000w.jpg 1000 x 600px 74 KB
cat-1200w.jpg 1200 x 700px 100 KB

まとめ

残念ながら、picture要素やsrcset属性を使ったレスポンシブ・イメージはまだ使わないのが得策のようです。

Picturefill 2.1.0について

いい感じで動いているのですが、画像が読み込まれる前にカラの画像の枠とaltテキストが一瞬表示されるという致命的な欠陥が残っています。また、フォールバックにsrcを使って画像を指定すると、一度その画像が表示されてからsrcsetに指定した画像が表示される(=無駄に画像が読み込まれる)という欠陥もあります。Picturefill 1.2では、こんなことはなかったと思うのですが。

レスポンシブ・イメージの大きな目的の1つは表示パフォーマンスの最適化なので、src属性は記述しないという選択肢しかないですが、一瞬とはいえ壊れた表示(カラの画像の枠とaltテキスト)が出てしまうのは、かなりイケてない体験です。これはジレンマですね〜

ブラウザでのネイティブ実装について

ブラウザへの実装は、Chromeでは良い感じに仕上がっていますし、38からの搭載が決まっているようなので楽しみです。しかし、FirefoxはNightlyでの実装を見る限り、33での搭載も「behind flags」で設定の変更が必要ですし、まだまだという印象を受けました。

2年前に比べればものすごい進歩ですが、レスポンシブ・イメージが普及するまでにはまだ時間がかかりそうです。また、ブラウザでサポートされても、実際に作るほうの手間も考えものです。

複数画像の作成がネックになりそう

今回デモ用に画像を作ってみて思ったのですが、結構手間がかかります。

この作業を簡単に自動化できる良いツールや手法がないと、レスポンシブ・イメージ利用のキャズム超えはまだ先なのかなぁと思います。

ベクター画像だったらSketchで解決できますけど、写真の場合は無理そうだし。Gruntだと設定がちょっと面倒だし。CodeKitあたりのStatic Site Generatorに実装されるのが理想でしょうか?Photoshopでプラグイン出てませんかね?

若干本末転倒な感じは否めないですが、いろいろな手間や将来性を考えたら、CMSやWebサーバで解決しちゃうという選択肢もありだなぁと思う今日このごろでした。

最後に & お願い

記事中の誤った情報のご指摘やレスポンシブ・イメージに関する最新情報やTipsなどがありましたら、このブログのコメント欄でもTwitter(@rriver)でも良いのでシェアいただければ幸いです。

“レスポンシブ・イメージがもうすぐネイティブ実装!いまから使える?ポリフィル「Picturefill 2.x」を検証” への1件のコメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です