SVGはそのリサイズ(スケーリング)においてブラウザ間で差異やバグがあります。有名なのはviewBox
がないことによるIE9やWebKitでのバグでしょうか。それでもimg
要素等でSVGを使う場合はSVG側でwidth
とheight
そしてviewBox
属性を指定し、CSSなどでリサイズすれば大体問題ありません。なので背景画像で使う場合もbackground-size
プロパティーを使えば……と思いきや、なかなかの落とし穴がありました。
Demo: SVG Arrow
WebKit以外では自動リサイズが期待されるviewBox
のみ指定したSVGを背景画像にすると問題なくキレイにリサイズされます。対してWebKitではリサイズされたりされなかったりです。しかもChromeとSafariでは挙動が少し違ったりもし、追求する気が失せるほど挙動不審です。どうも良きに計らってはくれそうにないので、明示的にリサイズを促す方法を探ってみました。
background-size
プロパティー.arrow {
background-size: 100% 100%;
}
まずは背景画像のサイズを指定するbackground-size
プロパティーを使用してみました。するとどうやらSVGをラスタライズしてからリサイズするようで、デモを見ればわかるようにぼやけます。ここでは%
を使っていますが、px
指定でのリサイズでも同じくぼやけます。
最初のデモと違い、このデモではSVG画像でwidth
とheight
属性を指定しています。これらの指定がないとそもそもうまくリサイズ出来なかったため、viewBox
属性と合わせた数を指定しましたが、その結果ぼやけるという……。
width
とheight
属性で100%
<svg
viewBox="0 0 64 64"
>
CSSでのリサイズはラスタライズされてからになってしまうということだと思うので、今度はSVGのルート要素のwidth
とheight
属性で100%
を指定してリサイズさせてみました。今度はうまくいった……と思ったんですが、同じSVG画像を更に使用した場合に片一方のリサイズ結果に引きずられてしまうという現象が起こりました。デモのように左の64px
へのリサイズ結果が128px
へのリサイズへ影響してしまうということです。場合によっては128px
の方が成功して、64px
の方が失敗するなどひどく挙動不審です。
::before
擬似要素で!.arrow {
width: 256px;
height: 256px;
}
.arrow::before {
display: block;
width: 100%;
height: 100%;
content: url("arrow.svg");
}
結局のところ背景画像で使う以上どうにもならなそうな気がしたので、目先を変えて::before
擬似要素のcontent
プロパティーでSVGを指定するという方法を試したところすんなりうまく行きました。WebKit以外でも問題ありません。
というわけでこのサイトのページング・ナビゲーションをSVGにしました。デモ・ページにも載っていますが矢印は以下のような単純なものです。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="left-arrow"
viewBox="0 0 64 64"
version="1.1"
xmlns="http://www.w3.org/2000/svg">
<g transform="translate(32), rotate(-45, 32, 32)">
<g fill="none"
stroke="#fff"
stroke-width="8">
<line x1="0" y1="4" x2="24" y2="4"/>
<line x1="4" y1="0" x2="4" y2="24"/>
</g>
</g>
</svg>
パスで書く必要もなさそうだったので、適当に線を組み合わせてカギ型にし、それをtransform
属性で移動(translate
)と回転(rotate
)を使ってシンプルなページング向けの矢印を作りました。
WebKit……というかブラウザのバージョンについて書いていなかったので追記しておきます。バグが起こるのはChrome 15.0.874.121 mとSafari 5.1.2です。Chrome 17.0.963.3 canaryでは完全に直っているので、デスクトップ界では結構すぐに統一されそうですね。