どういうこと?
タイトルが長いですが、要するにこういうことです。- CSSの background-image プロパティでSVG画像を表示する(背景画像とかCSS spriteとか)
- SVGに対応していない古いブラウザでは、フォールバック(代替)としてPNG画像を表示する
- JavaScriptを使わず、CSSのみで完結!
そのへんをうまい具合に表示する小技の紹介です。
代替画像は別にGIFとかJPGでもいいんじゃね?と思うかもしれませんが、どちらもベクトル画像の表現力が低いのでPNGを使いましょう。
ちょっと前置き
これをimgタグでやる方法はいろいろ開発されていると思うのですが(objectタグを使うとかsvgタグの中に書くとか)、background-image の場合はModernizr使おうず!というのが定説になっている感があります。そんな中、どうにかしてCSSだけで実現できないかと調べた結果、やり方を見つけたのでドヤ顔で紹介します。
多分日本語でここまで詳しく解説してる記事は他にはないと自画自賛。日本語以外でもないんじゃないかな。あったらごめんなさい。
ちょっと長くなりましたが、熱い想いを感じ取っていただいたところで本題に入ります。
とりあえず見せてよ
百聞は一見にしかず。まずはご覧ください。じゃん。
SVG fallback
わかりやすくするために、SVGとPNGで表示内容を変えています。SVG対応ブラウザでは"SVG"、非対応ブラウザでは"PNG"と表示されているはずです。ただし、IE9やAndroid 3.xなど一部のブラウザではSVG対応しているのにPNGが表示されてしまいます。
理由はあとで説明しますが、そういうもんだと割り切ってください。
どんなコード?
タネ明かしはこんなかんじ。問題の箇所だけ抜粋します。先にPNGを指定して、後から linear-gradient とかいうオマジナイで上書きするだけ。簡単。超簡単。
どういうことだってばよ
CSS3の新機能、multiple background-imageとlinear-gradientの2つを組み合わせています。- multiple background-image - 複数の画像を重ねあわせて背景画像を合成します。画像をカンマで列挙すると、列挙した順番で合成されます(順番が早いものほど前面)
- linear-gradient - グラデーション画像を作成します。今まではグラデーション画像を使いたければ実際にそういう画像を用意する必要がありましたが、CSS3では画像を用意せずに自動生成できる機能が用意されました。
linear-gradient(transparent, transparent) は単に透明な画像を生成しているだけなので、SVGと透明な画像を合成…つまりSVGを普通に表示しているのと同じです。
そしてこの子たちのブラウザサポート状況。
ブラウザ | multiple background-image | linear-gradient | 両方 | SVG |
---|---|---|---|---|
IE | 9+ | 10+ | 10+ | 9+ |
Firefox | 3.6+ | 16+ | 16+ | 4+ |
Chrome | 4+ | 10+ | 10+ | 4+ |
Safari | 3.1+ | 5.1+ | 5.1+ | 3.2+ |
Opera | 11.5+ | 12.1+ | 12.1+ | 10.1+ |
iOS | 3.2+ | 5+ | 5+ | 3.2+ |
Android | 2.1+ | 4+ | 4+ | 3+ |
Opera Mini | 5+ | - | - | 5+ |
どちらか一方でも対応していないブラウザでは、この指定が無視されてPNGが表示されます。
IE9など一部のブラウザでPNGが表示されたのはこういう理由です。お察しください。
おまけ その1
表を見ると、「multiple background-imageに対応しているけどSVGには非対応」というブラウザはFirefox 3.x、Safari 3.1、Android 2.xとかなり古いものばかりです。そんな化石は切り捨てる!という場合は、linear-gradient をなくしたこんな方法もあります。
さらに簡単になったよ。やったね!IE9やiOS 3.2、Opera MiniでもSVGを表示できるようになったよ。やったね!
そもそもSVG非対応のブラウザ自体が化石みたいなもんなので、これは実質IE8対策です。
IE8も切れるなら何も考えずに background-image にSVGを指定するだけでいいですよ。PNGも multiple background-image もいりません。
おまけ その2
全く別の切り口から、こんなやり方もあります。これは、同じくCSS3の新プロパティ background-size を画像と同時に指定しています。
"0 0"の部分は background-position の値を指定してください。CSS spriteで表示位置をずらす場合は両方の background プロパティに同じ値を指定する必要があります。
またまたサポート状況。じゃん。
ブラウザ | background-size | SVG |
---|---|---|
IE | 9+ | 9+ |
Firefox | 4+ | 4+ |
Chrome | 15+ | 4+ |
Safari | 7+ | 3.2+ |
Opera | 11.5+ | 10.1+ |
iOS | 7.1+ | 3.2+ |
Android | 4.4+ | 3+ |
Opera Mini | - | 5+ |
SVGの需要が高いスマートフォンで対応状況が悪い上に、場合によっては background-position を2度指定する必要のあるこちらの方法はあまり使えない感がありますが、せっかく調べたので紹介しておきます。
Sassのmixinを使えば2回指定の部分はあまり面倒じゃなくなるんですけどね。
まとめ
background-image でSVG/代替PNGを指定する方法を3つほど紹介。ただし、どれも(W3Cの仕様に基づくものではなく)SVGとCSS3新機能のブラウザ対応時期の差を利用したハックなので、ブラウザによってはSVGに対応しているのにPNGが表示されてしまうことがあります。
それでも画像自体は表示されるので実用上の問題はありませんが、必要以上のPNG使用を家訓で禁止されている方、医者に止められている方、SVG教の信者の方などはやっぱりModernizr使うしかありません。
ちなみに…
このテクニックはQiNeelでも使っています。最初の方法でね。参考
- SVG Fallbacks | CSS-Tricks
- A Complete Guide to SVG Fallbacks | CSS-Tricks
- Using SVG | CSS-Tricks
- Can I use... Support tables for HTML5, CSS3, etc
0 件のコメント:
コメントを投稿