gulpでsvgスプライト用画像を生成
フロントのデザインリニューアル案件があり、「せっかくだから画像もスプライトで表示したいね」と言う話がありまして。
最近webエンジニアにジョブチェンジした私には何が何やらだったのですが、「svgスプライト使います?」とデザイナーさんから提案があり、調べてみたところ結構便利そうだったので、思い切って導入してみました。
実際は導入コストも低く、思っていた以上に簡単で感動できたのでオススメです。
svgスプライトとは
複数のsvg画像を1つのファイルにまとめ、そのファイルから特定の画像を切り出して使うことでhttpリクエストを減らし、フロントエンドのパフォーマンスを向上させる方法です。
CSSスプライトも目的は同じです。
CSSスプライトの場合は、「1枚の画像ファイルの中から、目的の画像のある位置」をCSSで指定して表示するのですが、svgスプライトの場合は「画像そのものを指定」するイメージです。
嬉しいこと
httpリクエストが減る
画面内で小さいアイコンなどを複数使う場合、その都度全てのファイルをhttpでリクエストして取得することになるのですが、svgスプライトで画像をひとまとめにしておくとその分リクエストが減り、パフォーマンスが向上します。
CSSで色を変更することができる
CSSでスタイルを変更することが可能です。
色ごとにアイコンを用意する必要がないのでらくちん。
画像サイズの変更が容易
ベクター画像なので、画像サイズの変更が簡単です。
サイズごとに画像を用意する必要がないのでらくちん。
画像が増えても平気
gulpを使ってsvgスプライト用画像を作る場合、svg画像を所定のディレクトリに入れ、コマンドを叩くだけで生成できます。
画像が増えた時にもコマンドを叩き直すだけでいいのでらくちん。
実際に作ってみる
gulpを使ってsvgスプライト用の画像を生成します。
使ったのは以下のプラグインです。
-
gulp-load-plugins
-
各gulpのプラグインの読み込みを簡単にしてくれます
-
gulp-sass
など、gulp-
で始まるプラグインは$.sass()
のように、gulp-
以降のみの記載で呼び出すことができて便利 -
gulp-svgmin
-
svg画像を最適化し、ファイルサイズを削減するために使います
-
gulp-svgstore
-
複数のsvg画像を1つにまとめてくれるやつ
-
gulp-cheerio
-
svgに記載されている
fill
を削除するために使います -
削除しないとCSSで色を変更することができなくなるので要注意
-
fill
が指定されていない場合は黒で表示されるようなので、万が一色を指定を忘れても安心です
これらのプラグインを
npm install gulp-load-plugins
などでインストールします。
package.json
のdevDependencies
に追加したい場合は、--save-dev
を付けることでインストール時に一緒に追加されます。
インストールが終わったら、Gulpfile.js
に以下を追加します。
こちらをほぼコピペです。大変助かりました。。。
gulp.task('svg', function () {
gulp.src('img/sprite/icons/*.svg')
.pipe($.svgmin())
.pipe($.svgstore({ inlineSvg: true }))
.pipe($.cheerio({
run: function ($, file) {
$('[fill]').removeAttr('fill');
},
parserOptions: { xmlMode: true }
}))
.pipe(gulp.dest('img/sprite'));
});
これが準備できたら
gulp svg
を叩くだけでsvgスプライト用画像が生成されます。
やっていることは、imgディレクトリ配下のsvgファイル全てを対象にして
- svg画像を最適化
- svgスプライト画像の生成
-
fill
を削除 -
img/sprite
ディレクトリへ出力
です。
html側では
<svg role="image">
<use xlink:href="/img/sprite/icons.svg#image-name" />
</svg>
これだけで特定の画像を出力することができます。
ファイル名の後ろに付ける#image-name
の部分は、元となったsvg画像のファイル名を指定するだけで大丈夫です。
たったこれだけでsvgスプライトを実現できるので、ぜひお試しください。
注意点
実はIEではこの方法での画像表示に対応していないようです。
IE向けのポリフィル等も用意されているようなので、どうしても対応が必要な場合は別途導入が必要なのでお気を付けください。