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

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 を考慮するのであれば有効な場合があります)

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