こんにちは!
本日はSVGスプライトのお話をしてみようかと思います。

SVGスプライトってなんぞ?

cssスプライトって昔の手法でありましたよね。一枚画像でbackground-positionを変更するだけにすれば、画像リクエスト数を減らせるってヤツですね。
それのsvgバージョンかなぁと思っていたのですが、全然違いました・・・

いや、全然違うことはないのかな・・・

svgスプライトを一言でまとめるなら

svgファイルを一つにまとめて、使いたい時に呼び出そうぜ!

といったものかと。

svgをインラインで書くと、とんでもなくhtmlファイルが汚される気しませんか?
無駄に行数取られて、何個も書いた時には、メッチャ見にくくなるのがストレスでした。

SVGスプライトを使う前の手法

例えばよくあるFacebookのfマークをインラインで書くと

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="156px" height="300px" viewBox="0 0 156 300">
<path class="fill" d="M101.000,300.000 C101.000,300.000 101.000,163.000 101.000,163.000 C101.000,163.000 147.000,163.000 147.000,163.000 C147.000,163.000 154.000,110.000 154.000,110.000
C154.000,110.000 101.000,110.000 101.000,110.000 C101.000,110.000 101.000,76.000 101.000,76.000 C101.000,60.552 105.857,50.000 128.000,50.000
C128.000,50.000 156.000,50.000 156.000,50.000 C156.000,50.000 156.000,2.000 156.000,2.000 C151.113,1.351 134.503,-0.000 115.000,-0.000
C74.282,-0.000 46.000,25.336 46.000,71.000 C46.000,71.000 46.000,110.000 46.000,110.000 C46.000,110.000 0.000,110.000 0.000,110.000
C0.000,110.000 0.000,163.000 0.000,163.000 C0.000,163.000 46.000,163.000 46.000,163.000 C46.000,163.000 46.000,300.000 46.000,300.000
C46.000,300.000 101.000,300.000 101.000,300.000 Z"/>
</svg>

こんな感じに。

メッチャ長い・・・1つならまだしも、これが5つ6つとなってくると本当に無理だ・・・

ボクはこれが嫌すぎて、画像として扱うようになりました。

<img src="img/●●●.svg" alt="">

こんな感じ。

しかし、これだとcssで色の変更とかが出来なくなるので、svgの恩恵が50%くらい減ってしまいます。
ホバーで色を変えたい場合などは画像をもう一枚切り出して・・・jsでsrc変えて・・・みたいな。

凄く面倒だけど、やはり高解像度ディスプレイを気にしなくて良いという点で利用していました。

そんな時に出会ったsvgスプライト。

svgスプライトとの出会い

実は結構前からsvgスプライトの存在は知っていたのですが、冒頭に書いた通り、cssスプライトのsvgバージョンだと思っていたボクは学ぼうともしませんでした。

しかーし、最近またsvgスプライトの記事をよく見るようになったので、使ってみようと思ったが最後・・・ホントに何でもっと早く使わなかったのかと思うくらい便利なヤツでした!

という流れで今回の記事に至っております。

svgスプライトの設定をしよう

使う方法は色々あるみたいなのですが、今回はgulp-svg-spriteを使った方法をご紹介しようと思います。

gulpの使い方とかは調べればいくらでもあるので割愛・・・
早速いきましょう!まずはインストール!!

npm install gulp-svg-sprite --save-dev

そして、gulpの設定に入ります。オプションは色々あります。今回の設定はこちら。

var gulp = require('gulp');
var svgSprite = require('gulp-svg-sprite');

var baseDir = './resource';
var dist = './public';

// svgスプライト
gulp.task('svg-sprite', function () {
  gulp.src(baseDir + '/img/**/*.svg')
    .pipe(svgSprite({
      // 何で出力するか
      mode: {
        symbol: {
          'dest': '.', // どこに
          'sprite' : 'sprite.svg' // ファイル名
        }
      },
      shape: {
        transform: [
          {
            svgo: { // svgのスタイルのオプション
              plugins: [
                { 'removeTitle': true }, // titleを削除
                { 'removeStyleElement': true }, // <style>を削除
                { 'removeAttrs': { 'attrs': 'fill' } } // fill属性を削除
              ]
          }}
        ]
      },
      // 吐き出す際のオプション
      svg : {
        xmlDeclaration: true, // xml宣言をつける
        doctypeDeclaration: true // doctype宣言をつける
      }
    }))
    .pipe(gulp.dest(dist + '/img'));
});

ボクの今回の目的は、元々入っているfill属性、もしくはstyleタグを消した上で、svgを吐き出せればオッケーという感じでしたのでこれで問題なし。
ちなみにオプションをもっと知りたいぜー!という場合はこちらに色々載っています!

簡単に説明すると、

  1. resource/imgの中に全部svgファイルを入れる
  2. gulp svg-spriteコマンドを打つ
  3. public/imgの中に、sprite.svgという名前で全部のsvgファイルがまとめられたファイルが出来上がる
  4. 出来上がったsprite.svgから必要なものを使う

という感じです。

ポイントとしては、modeをsymbolで吐き出す所でしょうか。

svgスプライトを使ってみよう

では実際に使う時はどうするのか。
svgスプライトを利用するにあたって、キーワードはsymbolとuseです。

いや、実際は他にも色々使う方法はあるのだろうとは思うのですが、今回はsymbolとuseを利用します。

まず、svgではpathタグを囲むように<g>というのが入っていたりします。
svgスプライトでは、このgタグをsymbolタグに書き換えます。
gがないsvgとかもあったりしますが、ようは、pathをsymbolで囲ってやるということですな。</g>

それを踏まえて、gulp svg-spriteによって吐き出されたsprite.svgを見てみましょう。
今回はFacebookとTwitterのアイコンを入れてみました。

<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><symbol viewBox="0 0 156 300" id="facebook" xmlns="http://www.w3.org/2000/svg"><defs/><path class="afill" d="M101 300V163h46l7-53h-53V76c0-15.448 4.857-26 27-26h28V2c-4.887-.649-21.497-2-41-2-40.718 0-69 25.336-69 71v39H0v53h46v137h55z"/></symbol><symbol viewBox="0 0 350 300" id="twitter" xmlns="http://www.w3.org/2000/svg"><defs/><path class="bfill" d="M350.001 35.509c-3.975 6.658-9.352 13.688-16.131 21.086-5.377 5.918-11.926 11.961-19.639 18.125V79.53c0 1.232.115 2.096.348 2.589v2.589c0 25.401-4.557 50.864-13.676 76.389-9.118 25.523-22.094 48.397-38.928 68.618-18.004 21.702-39.862 38.841-65.581 51.419-25.72 12.577-54.477 18.865-86.272 18.865-20.576 0-39.98-2.958-58.218-8.877-18.703-5.92-36.005-14.304-51.905-25.155.937.247 2.338.371 4.209.371 3.74.493 6.547.739 8.418.739h4.557c16.367 0 32.384-2.835 48.048-8.508 14.496-5.425 28.172-13.316 41.032-23.674-14.963-.246-28.876-5.426-41.732-15.538-12.627-9.863-21.045-22.317-25.252-37.36 3.507.74 5.728 1.108 6.664 1.108h3.504c.704.247 1.755.371 3.158.371 2.103 0 3.741-.124 4.911-.371 2.337 0 5.612-.493 9.819-1.479.466 0 1.17-.124 2.104-.37.937-.247 1.636-.369 2.103-.369-16.601-3.453-30.277-12.208-41.033-26.265-10.989-14.057-16.48-30.086-16.48-48.088v-.371-.369-.37c4.442 2.959 9.586 5.179 15.431 6.658 6.078 1.972 11.805 2.96 17.184 2.96-10.29-7.398-18.004-16.4-23.147-27.004-5.846-10.851-8.768-22.936-8.768-36.252 0-7.398.817-14.057 2.454-19.976.937-4.193 3.274-10.234 7.015-18.125 18.237 23.673 39.979 42.169 65.231 55.487 25.953 14.303 53.54 22.194 82.766 23.675-.701-5.18-1.05-8.015-1.05-8.508-.471-3.453-.704-6.288-.704-8.509 0-20.962 7.015-38.841 21.042-53.637C205.512 7.396 222.462-.002 242.337-.002c10.286 0 19.988 2.096 29.107 6.288 9.118 4.685 16.95 10.605 23.498 17.756 7.481-1.727 15.43-4.192 23.846-7.398 7.015-2.713 14.263-6.412 21.744-11.097-2.803 8.877-6.898 16.892-12.272 24.044-6.081 7.398-12.509 13.316-19.291 17.756a319.095 319.095 0 0 0 21.041-4.44c5.378-1.479 12.042-3.946 19.991-7.398z"/></symbol></svg>

うーん、訳わからん・・・

注目すべきは<symbol></symbol>の間にpathが入っていて、それが連続されてるって所ですかね。

そして各symbolにはidが入っています。
実はこのid、元ファイルの●●●.svgの●●●の部分が勝手にid名として入ってくれています。

吐き出されたコードはどうでもいいので、放っておきましょう。
使うべきはこのsymbolに振られたidを利用します。

実際にhtml上でファイルを利用する時は、

<use xlink:href="img/sprite.svg#●●●"></use>

といった具合に、ファイルのパス→ファイル名→id名を組み合わせれば表示されます。
今回のケースだとこんな感じ

<svg class="facebook" role="img">
  <title>Facebook</title>
  <use xlink:href="img/sprite.svg#facebook"></use>
</svg>

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

なんということでしょう・・・これで表示されます。(titleとかroleとか入っていますが、この辺の説明は割愛します・・・)

htmlに書く量も少ない・・・
cssで色の調整も出来る・・・

完璧じゃないか!!!!!
もう感動レベルですよね。

svgスプライトの落とし穴

さて、こんな感じで無事表示されるかと思うのですが、いくつか問題点もあります。

  • 実際に見てはいないが、IE11で、useは使えないらしい(表示されない)
  • chromeで見たら表示されない

こんな問題がボクの調べた範囲では、確認されました。
解決していかなくては・・・

IE11問題

どこかのスゴイ人が便利なプラグインを作ってくれているので、それを入れちゃいましょう!!

svg4everybody

使い方もメッチャ簡単!!

<script src="/path/to/svg4everybody.js"></script>
<script>svg4everybody();</script>

これで終わり。
こっちもオプションがあるみたいですが、試していないので、何のオプションかは不明・・・

chrome見れない問題

どうやらローカル環境で見れないだけのよう。FirefoxやSafariだと問題ないのですが、chromeだけ、この現象が起こりました。

サーバー上では問題なく表示されるので、こちらは気にせず進める・・・
もしくは、gulpなどでローカルサーバーを立てる・・・

こんな感じで解決できました。

終わりに

今回もなんだかんだで、もの凄く長くなってしまった・・・
SVGスプライト・・・今まで見て見ぬふりをしてきましたが、使ってみると本当に便利だなぁと感じました!

実はまだ、実案件では使っていないので、次の案件は利用してみようかと。
もしかしたら、もう少しバグが見つかるかもしれないし・・・

使ってみようか悩んでいた方、svgをもっと効率よく使っていきたい方、

絶対使うべき!!!!

ということで、今回はSVGスプライトを使ってみたお話でした!
ありがとうございましたっ!!