Acceptヘッダで判別するサーバーサイドのSVGフォールバック
前回の記事ではSVGに未対応な環境が現在どの程度残っているのか調査しました。
SVG未対応ブラウザのシェアって今どれくらいか?2015年10月版
ブラウザシェアの調査は難しく、Webサイトの利用者層によっても傾向は異なるのでしょうが、NetMarketShareによれば未対応な環境は2割以下ほどになってきています。
しかし少数だからと言って全く無視をしてSVGだけを使うというわけにはいきません、なぜなら未対応の環境では表示されませんから、必要な情報を得られず困りますから、なんらかの形でフォールバックが必要になります。
簡易目次
- フォールバックとは
- SVG未対応の環境とは
- ダメなフォールバックの例
- インラインSVGのimage要素を使ったフォールバック
- 逆にSVG未対応の環境で余計なリクエストが行われるフォールバック
- JavaScriptを使ったフォールバック
- srcset属性を使ったSVGフォールバック・ハック
- Acceptヘッダとはなにか?
- WebP画像に対応しているなら、SVGにも対応している……はず
- まとめと、良いSVGフォールバックについて
- 補足などあれこれ
フォールバックとは
フォールバックとは、ある機能が利用できないときでも別の手段で代替とすることです。
例えば、回線状況の悪化で画像が見れない場合、または視覚障害者向けのスクリーンリーダーなどで利用できるようにalt属性を使いますね、これも一つのフォールバックです。
<img src="paint.jpg" alt="代替テキスト">
jpeg画像が見れないときにはalt属性が代わりに表示されますし、スクリーンリーダーであれば画像が見れない視覚障害者向けに音声として読み上げます。
SVGもimg要素で使えますが、このままでは未対応の古いブラウザでは表示できません。
<img src="paint.svg" alt="代替テキスト">
代わりのalt属性を設定するのは当然として、できれば
とさせたいわけです。
SVG未対応の環境とは
主要なモダンブラウザでは概ねSVGへの対応はされていますが、現在まで残っているSVG未対応の代表的な環境をピックアップすると、これらが挙げられます。
Inline SVG in HTML5 - Can I use...
IE 8以下 | Android 2.3.x以下 | フィーチャーフォン | ゲーム機 |
---|---|---|---|
IEは8以下、Android3は未満の標準ブラウザが未対応。さらにフィーチャーフォン、いわゆるガラパゴスケータイですね。
そしてゲーム機の対応状況はこのような感じ
名前 | SVG | レンダリングエンジン | ブラウザ | 仕様 | 発売/配信時期 |
---|---|---|---|---|---|
Wii インターネットチャンネル | × | Presto | Opera 9.x | URL | 2006年12月 |
WiiU ブラウザー | ○ | WebKit | NetFront Browser NX v3.0 | URL | 2012年11月 |
DSブラウザー | × | Presto | Opera 8.5 | URL | 2006年7月 |
DSiブラウザー | × | Presto | Opera 9.5 | URL | 2008年11月 |
3DSブラウザー | × | WebKit | NetFront(R)Browser | URL | 2011年6月 |
New 3DSブラウザー | ○ | WebKit | NetFront Browser NX v3.0 | URL | 2014年10月 |
PS3 | × | Mozilla? | URL | 2006年11月 | |
PS4 | ○ | Webkit | 2013年11月 | ||
PSP | × | Mozilla? | NetFront | URL | 2005年7月 |
PS Vita | ○ | Webkit | NetFront NX | URL | 2011年12月 |
任天堂のハードは、WiiUとNew 3DSからSVG対応されています。
PS4とPS Vitaは実機を所有していないため確かめられていないのですが、こちらのサイトによるとSVGに対応とのこと(PS4、PS Vita)。
なおXbox系はIEなので省略します。
こうした環境に対して上手く切り分けて、SVGと代替となるPNG画像を適切に表示させたいわけです。
それには様々な手段がありますが、まず最初にダメな例を紹介します。
ダメなフォールバックの例
日本経済新聞はダメな例として分かりやすいです。
日本経済新聞ではトップのロゴにSVGを使っています。
<div class="l-header_title"> <a href="/" id="JSID_TITLE"> <!--[if lte IE 8]> <img src="http://partsa.nikkei.jp/parts/ds/images/common/logo_nikkei_header.png" title="日本経済新聞" alt="日本経済新聞" /> <![endif]--> <!--[if gte IE 9]><!--> <img src="http://partsa.nikkei.jp/parts/ds/images/common/logo_nikkei_header.svg" title="日本経済新聞" alt="日本経済新聞"> <!--<![endif]--> </a> </div>
SVG未対応ブラウザへのフォールバックは条件付きコメントで行っています。
これは古いIE向けであれば有効に機能しますが、IE以外のレガシーな環境に対しては意味がありません。具体的に言えば、Android3未満の環境や3DSなどでアクセスすると代替であるはずのPNG画像も表示されません。
試しに3DSでアクセスした場合
このようにロゴが全くの空欄になってしまいます*1。古いIEのみを対象としたこうしたフォールバックは避けるべきです。
一方、ニューヨークタイムズで行われているフォールバックはこのようになっています。
インラインSVGのimage要素を使ったフォールバック
ニューヨークタイムズもロゴにSVGを使っています。ただしこちらで利用しているのはこうした手法です。
SVGの仕様に無いはずのsrc属性をimage要素に記述しているのが注目ポイントです。
<h2 class="branding"> <a href="http://www.nytimes.com/"> <svg class="nyt-logo" width="379" height="64" role="img" aria-label="The New York Times"> <image width="379" height="64" xlink:href="http://a1.nyt.com/assets/homepage/20151012-175041/images/foundation/logos/nyt-logo-379x64.svg" src="http://a1.nyt.com/assets/homepage/20151012-175041/images/foundation/logos/nyt-logo-379x64.png" alt="The New York Times" border="0"> </image> </svg> </a> </h2>
これはインラインSVGに対応したブラウザはimage要素として表示するの対し、SVG未対応の環境の場合ではimage要素をHTMLのimg要素として扱いsrc属性のPNG画像を表示する仕組みを利用したフォールバックです。
この手法は2013年8月に公開されて以降、その斬新さと適用範囲の広さでSVG界隈では話題になりました。ブラウザ環境を選ばす幅広く使えるのが大きな特徴で、条件付きコメントとは異なりSVG/PNG画像どちらも表示されないという最悪の事態が起きるブラウザは私の知る限りありません。
ただネックなのが、IE9〜IE11ではSVG/PNG画像どちらに対してもリクエストが行われる点です。(参考記事)
デモページ
(クリックで拡大)
つまりSVGに対応したIE9〜IE11では必要もないPNG画像が無駄にリクエストされるわけです、これがなければベストな方法なのですが……。*2
これとは逆にレガシーな環境で無駄なリクエストが生じるフォールバックもあります。
SVG未対応の環境で余計なリクエストがあるフォールバック
メジャーリーグのWebサイトでは各球団のロゴがSVGで作られています。
(The Boston Red Soxの公式サイトより)
そしてフォールバックはこのように行われています。
<a class="logobar__logo" href="http://boston.redsox.mlb.com/index.jsp?c_id=bos" data-phone-href="http://m.redsox.mlb.com/"> <img src="/documents/9/6/2/111260962/BOS_header_logo_htojzayw.svg" alt="BOS Wired Logo" onerror="this.onerror=null;this.src='/assets/images/8/1/0/111260810/cuts/BOS_1x_omwx1j3o_7o1v91an.png';"> </a>
SVGに対応していればそのまま表示されますが、SVG未対応のブラウザだとSVGが表示できませんから、エラーがでます。
それをerror
イベントで発火させてPNG画像に書き換える、という手法です。シンプルな構成で記述できるためメジャーリーグの全球団の他、ジャクソンビル市観光局やアメコミ出版社のDark Horse Comicsなど採用例は多いです。
ただこの手法の欠点はJavaScript無効では使えないこと、なによりSVG未対応の環境では
SVGファイル → エラー → PNG画像ファイル
と必ず不要なリクエストが発生する点がネックです。
しかしロゴに一つだけ使うのであれば記述も簡潔で済む点は魅力的な手法ではあります。
ただ複数のSVG画像を配置するケースにはパフォーマンスも低下しますから、JavaScriptライブラリを利用した方が良いでしょう。
JavaScriptを使ったフォールバック
JavaScriptを使ったフォールバックはSVGeezyといったSVGに特化したライブラリもありますが、Modernizrを使うケースが多いですね。
以前にこの記事を書いた際に調査したところ
SVGを使用してる企業・団体のサイトを22ヶ国、160件以上調べてみた
57件でModernizrを利用していました。
Modernizrの使い方はこちらの記事が参考になります。
SVG のフォールバックは結局 Modernizr に落ち着いた件 | WWW WATCH
ここではModernizrでSVG対応状況を判別し、jQueryでimg要素を書き換えてPNG画像を表示させるサンプルが掲載されています。
またModernizrは background-imageで利用する手もあります。
具体的な利用例としては、元国務長官のヒラリー・クリントン氏の公式サイトが分かりやすい使い方で参考になるでしょう。
ヒラリー氏の公式サイトではロゴにSVGを使っていますが、
Modernizrを使っていながらも、JavaScript無効の環境ならばPNG画像が表示されるように構成されています。
このようにJavaScript無効の環境であっても工夫次第で適切なフォールバックは構築できますが、可能ならJavaScriptには依存せずにいたいなー、と個人的に思うわけです。
またbackground-imageでも良いのですが、img要素でも使いたいですし。
srcset属性を使ったSVGフォールバック・ハック
そんなことを考えていたら、先日投稿された、Hail2u.netさんのこの記事が興味深い内容でした
srcset属性を使ったSVGフォールバック・ハック - Weblog - Hail2u.net
srcset属性を使ったSVGのフォールバック(ハック)でシンプルな構成ながら利点の大きい手法です。
<img src="foo.png" srcset="foo.svg">
この方法の利点は3点
- img要素で使える
- JavaScriptを使わない
- 画像のリクエストが1回で済む
レガシーな環境にはsrc属性で示した代替画像が表示され、モダンブラウザではsrcset属性のSVGが表示される仕組みです。
特に他の手法ではおざなりがちだった、不要なリクエストの問題が解決されるのが素晴らしいですね。
ただ欠点は、SVGが表示される対象が狭いこと。
Srcset attribute - Can I use
主だったところでは、SVGに対応しているにもかかわらず
これらの環境で代替のPNG画像が表示されてしまいます。
全く何も表示されないよりは良いものの、せっかくSVGが表示できるブラウザなのに、PNG画像になってしまうのは残念ですね。特にIE9〜11、Android4はまだまだ利用者も多いですし。
そこでようやく今回の表題である「Acceptヘッダで判別するサーバーサイドのSVGフォールバック」の話になります。srcset属性を使ったフォールバック(ハック)の利点を活かしつつ、それを補う形でさらにもう一つ別のフォールバックを組み合わせると適用範囲を広げれるのではないか?という実験的な内容です。
すげー長くなりましたが、ここまでが前置きで今からやっと本題です。
Acceptヘッダとはなにか?
それにはHTTPとはなにか?といった説明も必要になってくるのですが、そこまですると余計に長くなってしまうので、すごくざっくりと図で説明するとこんな感じです。
Webサイトを閲覧する際にはブラウザを利用してサーバー側に「貴方のサイトを見たいです」と要求(リクエスト)をします、それに対してサーバー側が返答(レスポンス)を返すことで実際に情報……HTMLや画像が見れるわけです。
もう少し具体的に言えば例えば、img要素の画像に対して
<img src="http://f.st-hatena.com/images/fotolife/r/rikuo/20151014/20151014230634.png" width="590" height="374" alt="">
Host: f.st-hatena.com User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0 Accept: image/png,image/*;q=0.8,*/*;q=0.5 Accept-Language: ja,en-US;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate Referer: http://d.hatena.ne.jp/rikuo/20151014 Connection: keep-alive Pragma: no-cache Cache-Control: no-cache
それに対してレスポンスはこのようになります。
Cache-Control:public, max-age=86400, s-maxage=1292 Connection:Keep-Alive Content-Length:32502 Content-Type:image/png Date:Fri, 16 Oct 2015 01:59:46 GMT ETag:"1103437556" Keep-Alive:timeout=7, max=5 Last-Modified:Wed, 14 Oct 2015 14:07:25 GMT Server:nginx/1.2.2 Via:1.0 squid.hatena.ne.jp:8080 (squid/2.7.STABLE6) X-Cache:MISS from squid.hatena.ne.jp X-Cache-Lookup:HIT from squid.hatena.ne.jp:8080
こうした情報はFirefoxなら
「開発ツール」から
「ネットワーク」を選択して
各項目を選ぶと確認できます。他のブラウザでも開発ツールで確認できます。
そしてリクエストにAcceptという項目がありますね。
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Acceptヘッダはコンテントネゴシエーションという機能の一つで、利用可能なファイルの種類を示すヘッダフィールドです。
これに記載されているimage/png
はPNG画像を示すContent-Typeで、かつて古いブラウザではPNG画像に対応していないことがありました。そのためAcceptヘッダに明記することで、このブラウザはPNGに対応していますよ、とサーバー側に伝えられます。
ちなみにChromeの場合、img要素で送信されるAcceptヘッダはこうなります。
Accept:image/webp,image/*,*/*;q=0.8
PNG画像に未対応な環境は現在はまずありませんから、省略するのは良いとして、今度はimage/webp
とWebP画像を示すContent-Typeが含まれていますね。
WebPはGoogleが中心となって普及を進めている画像形式で、ChromeやOperaで利用できます。
WebP image format - Can I use
参考リンク
現状はIEやFirefoxで表示できないためあまり使われていませんが、技術的にはこれを利用してリクエストで送信されるAcceptヘッダで判別して、WebPに対応しているブラウザにはWebP画像を、そうでなければPNG画像を返すこともできます。
参考:WebP - Webを速くするためにGoogleがやっていること Make the Web Faster 01 | HTML5Experts.jp
WebPの話はさておきSVGに話を戻すと、実はSVGでも同じようにAcceptヘッダに記述するブラウザがあります。意外に思うかもしれませんがそれはInternet Explorerです。
Fiddler and the IE9 Release Candidate - Fiddler Web Debugger - MSDN Blogs
主要なモダンブラウザで唯一 Acceptヘッダにimage/svg+xml
と記述しているんですよね、それもIE9〜IE11, Microsoft Edgeで。
IE9〜IE11で img要素の場合に送信されるAcceptヘッダはこうですね。
Accept: image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5
またMicrosoft EdgeではJPEG XRも追加されています。
Accept: image/png, image/svg+xml, image/jxr, image/*; q=0.8, */*; q=0.5
このことを利用することで、つまりこんなことができます。
というわけで、具体的にやってみましょう。
ここではApacheのmod_rewriteで設定します。.htaccess
にはこのように指定しました。
#Options MultiViewsを無効に Options -MultiViews # mod_rewriteを有効に RewriteEngine on # ディレクトリが存在せず RewriteCond %{REQUEST_FILENAME} !-d # svgファイルは存在する場合に RewriteCond %{REQUEST_FILENAME}\.svg -f # AcceptヘッダにSVGが含まれるなら RewriteCond %{HTTP_ACCEPT} "image/svg\+xml" [NC] # 条件に合致するなら、svgに RewriteRule ^(.*)$ $1.svg [L] # 上記条件以外ならばpngに RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME}\.png -f RewriteRule ^(.*)$ $1.png [L] # Vary HTTPヘッダ追加 <FilesMatch "\.(svgz?|png)$"> Header append Vary "Accept" </FilesMatch>
この例では同じディレクトリに同名のSVG/PNGを配置しています。
設定の意図を説明をすると、普段の使い勝手を考えて
<img src="paint.svg"> <!-- SVGを必ず返す --> <img src="paint.png"> <!-- PNGを必ず返す --> <img src="paint"> <!-- Acceptヘッダに応じてSVG/PNGを返す -->
と、拡張子まで記述してあればそれに応じたファイルを(Acceptヘッダに関係なく)返すように設定しています。
その上で、拡張子を省略した場合にはAcceptヘッダにimage/svg+xml
の記述があれば、SVGファイルをそうでなければPNGファイルを返すように指定。
そしてこれは同じURIで異なるコンテンツを返す設定ですから、こうした事例では検索エンジン向けにVary HTTPヘッダにAccept
を追加しておきましょう。
そんなわけでこちらがデモページ。
AcceptヘッダでSVG画像を振り分け
(IE11での表示)
Acceptヘッダに応じてSVGとPNGを振り分けます。
現状IE9〜IE11, Microsoft Edgeしか対象となりませんが、将来的に他のブラウザが対応すれば当然SVGが表示されます。ちなみにMicrosoft Edgeの場合はこのようになります。
(クリックで拡大)
Vary HTTPヘッダも記載されています。
ChromeはAcceptヘッダにimage/svg+xml
が含まれないためPNG画像が表示されます。
あと、Firefoxには先ほども紹介した、「開発ツール」から「ネットワーク」で
「ヘッダ」の「編集して再送信」で
要求(リクエスト)ヘッダを書き換えて再送信できる機能があります。
これを使えば手軽にAcceptヘッダを変えられるので、試しやすいかと。
というわけでこの方法と先のsrcset属性の手法と組み合わせたのがこちら。
<img src="paint" srcset="paint.svg">
デモページ
これは
- srcset属性に対応した最新ブラウザはSVGが表示
- srcset属性に未対応のブラウザの場合はsrc属性の指定が適用される
という動作になります。
これにより、srcset属性に未対応なIE9〜11でもSVGが表示されるようになりました。
Srcset attribute - Can I use
ただまだ、SVGに対応しているにもかかわらず代替画像が表示されるこれらの環境
については依然として解決していません。
そこでさらにもう一つ組み合わせてみました。
WebP画像に対応しているなら、SVGにも対応している……はず
上記で紹介した、WebP画像に対応した環境の表がありますね。
WebP image format - Can I use
WebP画像は
で対応しています(参考)。
割と新しいバージョンから対応が始まっているわけですが、そのいずれの環境でもWebP画像だけでなくSVGにも対応しているんですよね。
ならば
Acceptヘッダに
image/webp
が含まれていれば、SVGも対応しているはず
と言えるわけです。
そこで先ほどの.htaccess
の記述をこのように変えてみました
#Options MultiViewsを無効に Options -MultiViews # mod_rewriteを有効に RewriteEngine on # ディレクトリが存在せず RewriteCond %{REQUEST_FILENAME} !-d # svgファイルは存在する場合に RewriteCond %{REQUEST_FILENAME}\.svg -f # AcceptヘッダにSVG、またはWebPが含まれていれば RewriteCond %{HTTP_ACCEPT} "image/(svg\+xml|webp)" [NC] # 条件に合致するなら、svgに RewriteRule ^(.*)$ $1.svg [L] # 上記条件以外ならばpngに RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME}\.png -f RewriteRule ^(.*)$ $1.png [L] # Vary HTTPヘッダ追加 <FilesMatch "\.(svgz?|png)$"> Header append Vary "Accept" </FilesMatch>
デモページ
これで
- srcset属性に対応した最新ブラウザはSVGが表示
- srcset属性に未対応のブラウザの場合はsrc属性の指定が適用される
という動作を
- img要素で
- JavaScriptを使わず
- 画像のリクエストも1回で完了させる
この条件で設定できました。
しかしながら、これでも
Android3〜4.1 | ゲーム機 |
---|---|
これらのSVGに対応している環境にPNG画像が表示されてしまう問題は残っており、万全とは言えません。
ですが、
<img src="paint" srcset="paint.svg">
サーバーの設定は多少ややこしいですが、こうした記述でシンプルに書けるようになるのは便利じゃないかなー、と思うんですよね。
というわけで、以上が今回のAcceptヘッダで判別するサーバーサイドのSVGフォールバックでした。
まとめと、良いSVGフォールバックについて
様々なフォールバックの手法の利点と難点を説明・比較しつつ、今回の仕組みの解説を分かりやすく書こうとしたら随分と長い記事になってしまいました。それでもここまで読んでくださってありがとうございます。
最後に良いSVGフォールバックについて考えてみます。
……と言っても、一概に判断するのは難しいので逆に良くないフォールバックを挙げていくと理解しやすいでしょう。今回紹介した日本経済新聞のように代替画像が適切に表示されないのは論外として、良くないフォールバックは閲覧者に不要な負担のかかる手法……余計なリクエストが多用されるもの、JavaScriptなどの処理時間がかかるものが、そうだと言えます。
また制作者側の手間がかかるもの、も良くないフォールバックです。
既存のコンテンツを書き換える手順が複雑なものだったり、またPNG未対応の環境がそうであったように、SVGが表示できないレガシーな環境はいずれ何年かしたら無くなるでしょうから、そうした将来的にWebサイトを再び書き換える手間がかかってしまう手法というのも良いとは言えません。
その点でModernizrを使った手法はimg要素に新たに書き加えるものも少なくて済みますし、将来的にはスクリプトを適用しなければ良いだけなので優れたフォールバックと言えます。JavaScript無効の環境への対応の懸念はありますが。
それと比較して今回提案した、srcset属性&Acceptヘッダでのフォールバックは、閲覧者側・制作者側の両面から見て負担の少ない手法じゃないかな、と考えています。サーバーの設定は少し面倒ですし、JavaScriptライブラリを導入するより大変かもしれませんし、ベストでは決して無いかもしれませんが、そこそこベターな手段かなと。
またこの手法を着想するにあたって、これらの記事を参考に致しました。
後者は2012年の記事ですが、サーバーサイドでのSVGフォールバックの手法は海外のブログでもなかなか見かけないので非常に参考になりました。前者はまさにAcceptヘッダを用いた手法で、このテクニックも他に前例が見当たらない斬新なアイデアで今回の記事を書くに当たり大きく影響を受けました。
今回紹介した以外のSVGのフォールバックの手法についてはこれらの記事がまとまっています
補足などあれこれ
補足1:Acceptヘッダで判別はimg要素以外にも使えるか?
SVGはPNG画像などと同様に、img要素だけでなく様々な要素で使えます、そのいずれでも同じ手法が適用できるか?というと、一概にそうとは言えないんですよね。
Acceptヘッダは要素ごとに異なります、例えばIE11の場合はこのようになります。
img要素 | image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5 |
---|---|
CSS | image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5 |
input要素 | image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5 |
embed要素 | text/html, application/xhtml+xml, */* |
iframe要素 | text/html, application/xhtml+xml, */* |
object要素 | */* |
直接表示 | text/html, application/xhtml+xml, */* |
検証ページ
CSSはbackground-imageやborder-imageで指定した場合、直接表示はSVGファイルをそのまま表示させた場合です。
Microsoft Edge 20
img要素 | image/png, image/svg+xml, image/jxr, image/*; q=0.8, */*; q=0.5 |
---|---|
CSS | image/png, image/svg+xml, image/jxr, image/*; q=0.8, */*; q=0.5 |
input要素 | image/png, image/svg+xml, image/jxr, image/*; q=0.8, */*; q=0.5 |
embed要素 | text/html, application/xhtml+xml, image/jxr, */* |
iframe要素 | text/html, application/xhtml+xml, image/jxr, */* |
object要素 | */* |
直接表示 | text/html, application/xhtml+xml, image/jxr, */* |
Chrome 45
img要素 | image/webp,image/*,*/*;q=0.8 |
---|---|
CSS | image/webp,image/*,*/*;q=0.8 |
input要素 | image/webp,image/*,*/*;q=0.8 |
embed要素 | text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 |
iframe要素 | text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 |
object要素 | text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 |
直接表示 | text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 |
Chromeでは、object要素のtype属性によってAcceptヘッダは変わりますが、ここではimage/svg+xml
を指定した際の値を記載。
Firefox 41
img要素 | image/png,image/*;q=0.8,*/*;q=0.5 |
---|---|
CSS | image/png,image/*;q=0.8,*/*;q=0.5 |
input要素 | image/png,image/*;q=0.8,*/*;q=0.5 |
embed要素 | text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 |
iframe要素 | text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 |
object要素 | text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 |
直接表示 | text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 |
このように、要素によってAcceptヘッダは変わるため、img要素以外で利用するのはうまくいかないケースがあります。
補足2:UserAgent文字列を使うのはどうか
リクエストヘッダを利用するにあたりUserAgent文字列は良く使われています。
JavaScriptでも取得できることもあって、スマートフォン用にデザインを変更する際などにも設定しているケースは多いです。
ただ、UserAgent文字列を偽装できるアプリが多いんですよね。
古いAndroid向けのブラウザアプリ、フィーチャーフォン向けのjig browser、さらにはNew 3DSにもUserAgent文字列を変更できる機能がついています。使いやすい一方で、不確かな情報を元に判別するのはなるべく避けたいな、と私は考えています。
補足3:Acceptヘッダの偽装について
AcceptヘッダはUserAget文字列のように偽装ができない、というとそうでもなく上述の通りFirefoxの開発ツールなどで変更してアクセスすることは可能です。
ただ偽装するケースは滅多にないでしょう。
補足4:CSSだけでSVGフォールバック
ちなみにCSSだけで行うSVGフォールバックならCSS Gradientsを活用すると良いです。
div{ background: url("fallback.png"); background: url("background.svg"), linear-gradient(transparent, transparent); }
デモページ
この手法はCSS Gradients対応環境とSVG対応環境がかなり似ていることを利用したフォールバックで、ミスマッチも少なくかなり使いやすいです。
SVG/PNGどちらも表示されない最悪の状況はありませんし、SVG対応環境で代替画像が表示されてしまうケースは
- IE9
- Android3
- Opera mini
- WiiU, New 3DS(PS4, PS Vitaは未検証)
参考:CSS Gradients - Can I use
これらになります。やはりこれだけで完璧というわけではありませんが、シンプルに書けますし使用しやすいでしょう。
><