svg-spriteで無駄の無い
SVGスプライトを生成する

最近のWebサイトで使われることが多くなったSVG画像ですが、私が現場で行っているSVGスプライトの生成方法、実装方法をご紹介します。

SVGスプライトとは

近年行っていたスプライト画像のように、1つのファイルに複数のSVG画像を扱う手法です。
SVGスプライトには複数の指定方法がありますが、今回はsymbol要素に変換して、それをHTMLでuse要素を使用して指定する方法をご紹介します。

SVGスプライトを作る

前提で以下のディレクトリ構成で話を進めます。

/project
├ /assets
│ └ /svg //SVGスプライトの格納場所
├ /svg  //単体のsvgファイル
└ index.html

svg-spriteをインストールする

SVGスプライトの生成には、svg-spriteを使用します。
今回は、svg-spriteのREADMEと同じように、npmのGlobalにインストールします。

$ npm install svg-sprite -g

svg-spriteの設定

続いて、svg-sprite用の設定ファイルを作成します。
コマンド実行のオプションでも様々な設定は行えますが、運用を踏まえて設定ファイルを作成する形を取ります。
設定ファイルの作成場所は、プロジェクトのルートディレクトリか、configディレクトリなどを作成して、そこに配置する方法が望ましいでしょう。今回はプロジェクトのルートディレクトリに作成します。
設定内容は以下のとおりです。

config.json
{
  "dest": "assets/svg",
  "mode": {
    "symbol": {
      "dest" : ".",
      "sprite": "sprite.svg"
    }
  }
}

出力先が assets/svg 、その中にsprite.svgを生成します。

SVGスプライトを生成する

以下のようなコマンドを実行します。

$ svg-sprite -C config.json svg/*svg

svgディレクトリ内の単体svgファイルをまとめた sprite.svg が、 assets/svg に生成されます。

HTML上での扱い方

HTML

HTMLでは以下のようにSVGを指定します。

<svg class="logo" role="img">
  <title>DeNA</title>
  <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/assets/svg/sprite.svg#logo"></use>
</svg>

use要素xlink:href属性にSVGのパス、その後ろに表示させたいSVGの名前をIDで指定します。
SVGの名前は、単体のSVGファイル名にあたります。SVGスプライトを生成するときに自動で付与されます。

CSS

svg要素に直接widthheightを指定することもできますが、レスポンシブに扱いたい場合を考慮して、SVGの表示サイズはCSSで行うのが適切です。例えば以下のようにメディアクエリーを用いて、デバイスの画面サイズが変わる毎にSVGも大きさを変えることができます。

style.css
.logo {
  width: 120px;
  height: 60px;

  @media (max-width: 640px) {
    width: 80px;
    height: 40px;
  }
}

CSSで色を指定できるようにする

前述の手順を行えば、簡単にSVGスプライトを生成することができます。SVGを扱う利点の1つに、どれだけ拡大しても綺麗なアンチエイリアスを保ったまま扱うことができます。もう一つの利点として、SVGの塗の色をCSSで指定することも可能です。しかし、先程までの手順で作られたSVGスプライトではCSSで色を指定することができません。

色が指定できない理由

用意したSVGにもよりますが、通常だと塗りがfill属性に色が設定されています。SVG内でこれらの属性が設定されてしまうと、CSSでの設定を行うことができません。
ですので、fill属性を削除する必要があります。

SVGの色指定を削除する

SVGはXML形式なので、用意した単一のSVGファイルをエディターで開き、fill属性を探して消す…と手作業で行う事も可能ですが、その作業をsvg-spriteにお願いすることができます。

svg-spriteにはsvgoというSVGを最適化するライブラリが備わっています。デフォルトでいつくかの設定がされていますので、上記で書き出したsprite.svgも余計なタグなどは削除されています。
そしてこのsvgoの設定を追加することができます。今度はsvgo用の設定ファイルを作成して、以下のように設定してください。

svgo.json
{
  "plugins": [
    { "removeTitle": true },
    { "removeAttrs": { "attrs": "fill" } }
  ]
}

続いて以下のコマンドを実行します。

$ svg-sprite -C config.json --shape-transform-svgo svgo.json svg/*.svg

--shape-transform-svgoオプションを追加することでsvgo.jsonを読み込みます。これで新たに書き出されたsprite.svgにはfill属性が削除され、CSSから色の指定を行う事ができます。

CSSで色を指定する

あとは対象のクラスにfillで色を指定するだけです。

style.css
.logo {
  fill: #f00;
  width: 120px;
  height: 60px;

  @media (max-width: 640px) {
    width: 80px;
    height: 40px;
  }
}

このように、CSSで色を指定できるようになると、状態に応じた画像を別々で用意することも無く、大きさに応じた画像を用意する事もありません。また、SVGの設定はCSSで行っているので、transitionanimationを使用することで通常の画像とは違った表現を行えます。

タスクランナーでより複雑なSVGスプライトを作る

svg-spriteにはGrunt版、Gulp版が用意されており、複数のタスクを作成することで、複雑なSVGスプライトを作る事もできます。例えば、fillを消したいSVG、消したくないSVGを、まとめて1つのSVGスプライトにすることも可能です。

IE11に対応させたい

IE11は、SVGの表示に対応していますが、use要素での表示方法には対応していません。対応させるには、svg4everybodyを使用しましょう。
例外な記述を追加する事無く、他のブラウザと同じ記述で表示させることができます。

デザインに適した選択を

今回ご紹介したSVGスプライトですが、実装するデザインによっては適していない場合があります。
例えば、ディティールが複雑な画像は、ベクターデータにすることでファイルサイズが大きくなってしまいます。また、レスポンシブではないPCのみの実装であれば、SVGにすることもありません。(Retinaを考慮するのであれば有効な場合があります)

どの画像形式で表示するかは、実装するデザインをよく確認して、より適切な画像形式を選択してください。