SVGはそのリサイズ(スケーリング)においてブラウザ間で差異やバグがあります。有名なのはviewBoxがないことによるIE9やWebKitでのバグでしょうか。それでもimg要素等でSVGを使う場合はSVG側でwidthheightそして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画像でwidthheight属性を指定しています。これらの指定がないとそもそもうまくリサイズ出来なかったため、viewBox属性と合わせた数を指定しましたが、その結果ぼやけるという……。

SVGのwidthheight属性で100%

<svg
  viewBox="0 0 64 64"

 >

CSSでのリサイズはラスタライズされてからになってしまうということだと思うので、今度はSVGのルート要素のwidthheight属性で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では完全に直っているので、デスクトップ界では結構すぐに統一されそうですね。