外部のCSSを参照したSVGは思うように参照できるか

おおおお、なるほどー!

ただやっぱり、CSSの外部参照は厳しそうですね。

SVGから外部スタイルシートを参照するその他の方法

SVGから外部CSSを読み込む方法としては、記事にあるxml-stylesheet PIを使う他に、SVGの<style>要素を使うという手がある。SVGCSS使う際にも @import が使えるので、そこから参照してやればよい。あ、XMLだから要素の内容はちゃんとCDATAセクションで囲ってね。

<style><![CDATA[ @import url(external.css); ]]></style>

<svg:style>を使ったSVGファイルを直接開いたら、PIの例と同じようにChrome (dev), Firefox (beta), Opera (Next)は外部スタイルシートが適用された。ただSafari 5.1はCSSが適用されず。どうやら去年からの一年間にWebKitがちょっと良くなったらしい。

他にCSSを外部参照する仕組みがないか調べてみたら、Doug Shepersのエントリが引っかかった。SVG<style>も紹介されているけど、彼が思いついたのはHTMLの<link>で参照させるというもの。HTMLのNamespace (http://www.w3.org/1999/xhtml) を宣言して、HTMLの<link>要素をNamespace prefix付きでそのまま書けばいい。

<html:link rel="stylesheet" href="external.css" />

すごいよDoug…。とてもXMLっぽい使い方だ。

というわけで<html:link>を使ったSVGファイルも作ってみた。こっちはなんとSafari 5.1もOKだった。

SVGのreferencing modes

さて、どの方法でも直接開くと外部CSSファイルを参照できることがわかった。でも件の話はbackground-imageでの参照について。試したところどちらも、Opera以外でダメだった。

となると、たぶん想像されてる中にあると思うんですが、原因はSVGのreferencing modesでしょうねと。

SVG画像にはいろんな参照方法が考えられる。<img>background-imageで画像として読み込む方法と、<object><iframe>からオブジェクトとして埋め込む方法。

このうち、画像として読み込む<img>background-imageは、セキュリティなどの絡みで制限がかけられている。SVG内のスクリプトは実行されない、クリックイベントなどを受け付けない。<object>などオブジェクトはOK。

で、どうやら外部参照も制限されるもののひとつらしい。ためしに<object>経由で参照させてみるとうまくいった。

この制限される項目と、埋め込む方法の組み合わせは“referencing mode”として、SVG Integrationなる文書にまとめられている。書いたのはさっき紹介したDoug。

この文書では<img>で推奨されるモード、background-imageで推奨されるモードどちらでも外部参照が“yes”となっている。ただ、これが正式な仕様というわけでもないので、実装は違う。

Same-originなリソースでも参照は難あり

外部参照については、same-originなリソースに限定しようかというノートがSVG WGのWikiにある。

ただ、same-originなリソースでも、それがまだどこかにリダイレクトしていたら問題で、という懸念事項が書かれている。

で、こういった理由をふまえて、Mozillaは外部参照をしないように実装を変えた経緯があったみたい。Firefox 4のbeta段階で修正が入っている。

外部参照をしたいユースケースとして提示されていたのが、SVGファイル内部からバイナリ画像であったり他のSVGファイルを参照したい、というもの。これらの場合はdata: URLにすればいいだろう的なアドバイスがなされている。

ただ、ここでしたいのは外部CSSの情報を適用することなので、ちょっと解決できなそう。