[Gulp]SVGスプライト画像を自動で生成。複数のSVGアイコンを一つにまとめて背景画像にも対応。


[SVG sprite](https://github.com/jkphl/svg-sprite)の[gulpプラグイン](https://github.com/jkphl/gulp-svg-sprite)を利用し、複数のSVGアイコンからスプライト画像を生成するタスクを設定してみました。
自動処理なのでアイコンの追加・削除・更新を検知して都度まとめてくれます。
```<svg>```タグで書いてもよし、CSSの```background```で背景として表示してもよし。

※gulpやnpmのインストールはすでに済んでいる前提です。

## 検証環境

- nodeバージョン：8.12.0
- npmバージョン：5.3.0
- gulpバージョン：CLI version 3.9.1

## ディレクトリ構造

<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/56fc464f-6d5c-878f-ee85-83a309312eb0.png" alt="プロジェクトディレクトリ構造" width="836" height="273">


```_src/images/svg-sprite/``` ディレクトリからSVGアイコンを取得し、 ```_dest``` ディレクトリ内にスプライト画像と背景指定用のcssファイルをアウトプットします。

↓アウトプットされたファイル例
<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/0ab32ed4-2d81-cbec-92b0-dbbc1fce4d47.png" alt="_destの中身" width="802" height="242">

## 各種設定

### package.json


```package.json
{
  "name": "svg-sprite",
  "version": "1.0.0",
  "description": "svg-sprite gulp task",
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-svg-sprite": "^1.5.0"
  },
  "private": true
}

```

```name``` や ```description``` は任意のテキストで設定してください。

### gulpfile.js

gulpfile.jsの設定は完全に理解していない部分もあるので、正確な書き方は[公式ドキュメント](https://github.com/jkphl/gulp-svg-sprite)を見ていただければと思います。

```gulpfile.js
var gulp = require('gulp'),
svgSprite = require('gulp-svg-sprite');

// タスク
gulp.task('sprite', function() {
  return gulp.src('_src/images/svg-sprite/*.svg') // 元となるSVGアイコンのパス（*.svg で全SVGを対象に）
    .pipe(svgSprite({
      mode: {
        symbol: {
          // スプライト画像を置くディレクトリ名。指定しないとデフォルト設定（svg）に。
          dest: 'images',
          
          // スプライト画像のファイル名
          sprite: 'sprite.svg',

          // スプライト画像のプレビュー用HTMLが欲しい人はこちらも記述してください。
          // 任意の場所とファイル名を指定してください。
          example: {
            dest: '../css/svg-sprite-preview/sprite.html',
          }
        },
      } // mode
    }))
    
    // 書き出し先
    .pipe(gulp.dest('_dest')),

  // 背景用スプライト画像を指定
  gulp.src('_src/images/svg-sprite-bg/*.svg')
    .pipe(svgSprite({
      mode: {
        css: {
          // 背景用スプライト画像のファイル名を指定
          // ただし自動で接尾辞がつく
          sprite: '../images/sprite-bg.svg',
          
          // class名の接頭辞を指定。なぜか頭にドットが必要（例）.icon_home
          prefix: '.icon_%s',
          
          // サイズ指定用classの接尾辞（例）.icon_home_dims
          dimensions: "_dims",

          render: {
            // CSSファイル名を指定
            css: {
              dest: 'sprite.css',
            },
            
            // SCSSファイルも生成する場合はこちらも記述
            // 相対パスで _src ディレクトリ内を指定
            scss: {
              dest: '../../_src/sass/_sprite.scss',
            }
          },

          // スプライト画像のプレビュー用ページが欲しい場合はこちらも記述
          // 任意の場所とファイル名を指定
          example: {
            dest: 'svg-sprite-preview/sprite-bg.html',
          }
        }, // css

      } // mode
    }))

    // 書き出し先
    .pipe(gulp.dest('_dest'));
});


// 自動処理の設定
gulp.task('default', function() {
  gulp.watch('_src/images/{,**/}*.svg',['sprite']);
});

```

## gulpを実行

以上の設定ファイルを作成しnpmインストールも行ったら、以下のコマンドでgulpを実行してください。

```
gulp sprite
```


これで ```_dest``` ディレクトリ内に

- css/
	- sprite.css
	- svg-sprite-preview/
		- sprite-bg.html
		- sprite.html
- images/
	- sprite.svg
	- sprite-bg-7b55828d.svg

というファイルが、さらに```_src``` ディレクトリ内に

- _src/
	- sass/
		- _sprite.scss


と、それぞれファイルが追加されています。

## HTMLの設定

実際にスプライト画像を使ってアイコンを表示するには以下のように書きます。

### head

```html
<head>
  <link rel="stylesheet" type="text/css" href="css/sprite.css">

  <!-- SVG非対応ブラウザ用ポリフィル -->
  <script src="js/svg4everybody.js"></script>
  <script>svg4everybody();</script>
</head>
```

SVG非対応ブラウザ用ポリフィルは[svg4everybody](https://github.com/jonathantneal/svg4everybody)を利用しています。

### body

#### svgタグを使って表示

元のSVGアイコン```home.svg``` を表示する場合は

```html
<svg class="icon">
  <use xlink:href="images/sprite.svg#home" />
</svg>
```

というように、```<use xlink:href="``` の値が ```〜.svg#元のファイル名``` となります。

サイズや色の変更するはCSSを使います。

```css
.icon {
  width: 32px;
  height: 32px;
  fill: red;
}
```

ブラウザの検証機能で見るとこのようになります。
<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/f4805eb4-0dc3-d0a2-c9b3-004e27bbc7e3.png" alt="SVGスプライト表示サンプル" width="664.5" height="320.5">



#### backgroundを使って表示

```_dest``` 内の ```sprite.css``` のclassを使います。

```sprite.css
.icon_heart {
  background: url("../images/sprite-bg-7b55828d.svg") 0 100% no-repeat;
}

.icon_heart_dims {
  width: 32px;
  height: 32px;
}
```

```gulpfile.js``` でclass名の接頭辞を指定しているので、
```.icon_元のファイル名``` と ```.icon_元のファイル名_dims``` をセットで使用します。

```html
<span class="icon_heart icon_heart_dims"></span>
```

ブラウザの検証機能で見るとこのようになります。
<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/a90b0bcb-d00c-eab6-7150-790d8fb5a095.png" alt="SVGスプライト表示サンプル（background版）" width="668.5" height="445">

[ポリフィル](https://github.com/jonathantneal/svg4everybody)を使うことでIE11でも問題なく表示されます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/ba443e18-dae9-8013-6d23-e4899874748d.png" alt="IE11による表示" width="406" height="338">

## プレビュー用ページ

```gulpfile.js``` に

```gulpfile.js
example: {
  dest: 'svg-sprite-preview/sprite-bg.html',
}
```

このように書きましたが、これを書いておくことでSVGスプライト画像のプレビュー用ページが生成されます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/f72c6af1-ecea-913e-d2c5-63f7e7202349.png" alt="SVGスプライトのプレビューファイル" width="601.75" height="335">

このページを見ればアイコン名がひと目で分かるので、```<svg>``` やclass名で指定する際にとても便利です。


## 補足

```background``` を使う際のサイズ変更はCSSの```transform: scale(*);``` を使うしか無いようです。
※参考「[アイコンファイルをラクラク管理！『SVG sprite』を使いこなそう](http://liginc.co.jp/404217)」

また、背景で使うと```fill```で色を変更することが出来ないので、背景用の色でアイコンを用意しておく必要があります。自分が知らないだけで変更方法があるのかもしれませんが…。

---

以上です。

```<svg>``` による表示と、```background``` 指定の両方に対応するスプライト画像生成が上手くいかずハマってしまったことがあったので、この[SVG spriteのgulpプラグイン](https://github.com/jkphl/gulp-svg-sprite)で両方に対応出来るのは嬉しいですね。

参考になりましたら幸いです。

---

下記のページを参考にさせていただきました。ありがとうございます。

▼SVG sprites
https://github.com/jkphl/gulp-svg-sprite

▼SVG for Everybody
https://github.com/jonathantneal/svg4everybody

▼アイコンファイルをラクラク管理！『SVG sprite』を使いこなそう
http://liginc.co.jp/404217

▼svg-spriteで無駄の無いSVGスプライトを生成する
https://design.dena.com/engineering/svg-sprite/