SVGスプライトって、なんか複雑なイメージがありませんか?
僕はそうでした。なんか、面倒くさそう。。。どこから始めて良いかわからない。。。といった感じでずっと手をつけられずにいました。
でも、今回やってみて思ったんですが、一度ワークフローを確立してしまえばアイコン管理がかなり便利になります。CSSスプライトの時よりも管理が楽になりますし、表示サイズや今後の高解像度対応を気にしなくて良くなるのも嬉しいですね。
SVGスプライトについての英語のリソースはあるのですが、説明が多く、とっつきにくいものも多い印象なので、ここではできるだけシンプルに必要なことだけをまとめてみたいと思います。
では、SVGスプライト・アイコンシステムのGulpを使ったワークフローの構築、始めましょう!
目次
達成したいこと
- CSSスプライト と同等のことをSVGで実現する
- 表示速度改善のためにSVGアイコンを1つの外部ファイルで読み込む
- SVGスプライト画像作成の自動化
- フォールバック用PNG画像作成の自動化
- SVGアイコンのCSSでの色指定
デモページ
このワークフローで作ったSVGアイコンを使ったデモページはこちら から。
SVGスプライトの仕組み
SVGスプライトのアイコンシステムの構築にはいくつか方法がある ようですが、ここでは個人的に一番シンプルで簡単だと思った方法をご紹介します。symbol
タグを使って複数アイコンを1つのSVGファイルに記述し、svg
のuse
タグから参照する方法です。
<symbol>で複数アイコンを1つのSVGファイルに記述
まずは、以下のように複数のアイコンが入ったSVGファイルを作ります。ポイントは<symbol>
要素にid
とviewBox
が指定されているところです。
id
はuse
でアイコンを参照する際に使います。viewBox
では、それぞれのアイコンのサイズを指定します。アイコンのサイズは全て同じである必要はありません。
<svg xmlns="http://www.w3.org/2000/svg" class="hide">
<symbol id="hogehoge" viewBox="0 0 32 32">
<!-- 1つのアイコンのpathやshapeなどのSVG要素 -->
</symbol>
<symbol id="gehogeho" viewBox="0 0 32 32">
<!-- 1つのアイコンのpathやshapeなどのSVG要素 -->
</symbol>
</svg>
注: ページ上でのアイコンの表示サイズはCSSで指定するので、viewBox
ではsymbol
内のどの部分を表示するかを指定します。
<use>で外部SVGファイルの<symbol>部分を参照する
SVGファイルをsvg/icons.svg
として保存した場合、HTMLでは以下のようにアイコンを呼び出します。symbol
タグに#hogehoge
のIDを持つ1つ目のアイコンを読み込むには、以下のように記述します。
<svg>
<use xlink:href="svg/icons.svg#hogehoge" />
</svg>
これだけです。
ブラウザサポートを考えると面倒ですけど、基本的な仕組みはシンプルですね。
ブラウザサポート
XLinkとSVGのfragment identifierという仕組みを利用した方法なのですが、IEとEdgeを抜かしたSVGをサポートするモダンブラウザでサポートされているとのことです。とりあえず以下で動作確認できました:
- Chrome 46 (Mac / Win)
- Firefox 42 (Mac / Win)
- Safari 9.0
- Mobile Safari 9.0 (iOS 9.1)
- Chrome Mobile 46 (Android 6)
- Android 4.4 Chrome (BrowserStack / Nexus 5)
- Android 4.1 Browser (BrowserStack / Galaxy S3)
IEでのサポート
IEはsvg4everybody というポリフィルを使ってフォールバックの実装が可能です。以下の仮想マシンでsvg4everybodyの動作確認ができました。
- IE9 on Win 7
- IE11 on Win 7
- IE8 on Win 7(PNG画像にフォールバックされるところまでは動作確認できました)
MS Edgeでのサポート
Edge Dev のMSEdge on Win10 (Edge 20.10240.6384.0)で確認したところ、表示されませんでした。Edgeではuse
を使った外部ファイルの読み込みがサポートされていないようなのですが、11月にリリースされたBuild 10586のEdgeHTML 13で機能が実装された とのことです。
用意するもの
さて、ここからはSVGスプライトを作る方法をまとめていきます。用意するのは以下の2つです。
- SVGアイコン
- Gulp環境
今回の検証のために作ったデモ・ファイルは全てgithub にアップしてありますので、良かったらご参照ください。
SVGアイコン
複数のアイコンを個別にSVGフォーマットで保存します。 svg/icons/
など、決まったフォルダに保存しておきます。
Gulp環境
Gulpの方が設定ファイルなどの記述がシンプルで楽なのでGulpでやってます。以下のプラグインを使います。
gulp-load-plugins
各プラグインの読み込みを簡素化するためのプラグイン。なくても良いですけど、あるとgulpfile.js
の記述が便利です。
gulp-svgstore
複数のSVGアイコンを1つのSVGファイルにまとめてくれるプラグイン。
gulp-svgmin
SVGOでSVGファイルの最適化をするプラグイン。今回のデモでも、これを使ったら3KBくらい節約できました。
gulp-svg2png
SVGをPNGに変換してくれるプラグイン。フォールバック用のPNG画像を作るために使います。
gulp-imagemin
画像最適化プラグイン。自動変換したPNG画像の最適化に使います。
gulp-cheerio
HTMLとXMLの書き換えプラグイン。SVGに記述されているfill
を削除したり、HTMLにインラインで<svg>
を記述した場合に非表示にするためのクラスを追加します。
※ SVGでfill
が指定されていると、CSSで色指定が出来なくなるので削除しておきます。fill
が指定されていないとアイコンはデフォルトでは黒で表示されます。
gulp-rename
ファイル名を変更するプラグイン。フォールバック用のPNG画像ファイルの名称変更に使います。
導入ステップ
導入ステップをまとめると以下のようになります。
- SVGアイコンを特定のフォルダに保存
- gulpとプラグインのインストール
- gulpfile.jsの設定
- svg4everybodyの設置
- HTMLとCSSの記述
1. SVGアイコンを特定のフォルダに保存
SVGアイコンをsvg/icons/
に保存します。gulp-svgstoreを使って、このフォルダに入れた複数のアイコンをsvg/icons.svg
にまとめます。
2. gulpとプラグインのインストール
gulpと一覧にしたプラグインを全てインストールします。github にpackage.json
ファイルをアップしてあるので良かったらご利用ください。
3. gulpfile.jsの設定
svgstoreを使って複数のSVGアイコンを1つのファイルに統合する設定を行う「svg」というタスクとフォールバック用のPNG画像を作成する「svg2png」というタスクの2つに分けてgulpfile.js
を設定します。
最終的なgulpfile.js
はgithub にアップしてありますので、そちらをご参照ください。
まずはじめに、gulpとgulp-load-pluginsを読み込みます。gulp-load-pluginsでpackage.json
にあるプラグインをここで読み込まなくても$.svgstore
などと書いてで呼び出せるようにしています。
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
svgタスク
svg/icons/
にあるSVGファイルを、まずはgulp-svgminで最適化して、gulp-svgstoreで1つのファイルに統合。統合したファイルをgulp-cheerioを使って編集しています。
gulp.task('svg', function () {
gulp.src('svg/icons/*.svg')
.pipe($.svgmin())
.pipe($.svgstore({ inlineSvg: true }))
.pipe($.cheerio({
run: function ($, file) {
$('svg').addClass('hide');
$('[fill]').removeAttr('fill');
},
parserOptions: { xmlMode: true }
}))
.pipe(gulp.dest('svg'));
});
gulp-cheerioの説明の所でも書きましたが、SVGでfill
が指定されていると、CSSで色指定が出来なくなるので削除します。fill
が指定されていないとアイコンはデフォルトでは黒で表示されます。また、HTMLにインラインでSVGを読み込んで使用する場合にSVGスプライトが表示されないように<svg>
にhide
というclass
を追加しています。
svg2pngタスク
svg/icons/
にあるSVGファイルをPNGに変換。svg4everbodyのデフォルトの動作に合わせてgulp-renameを使ってファイル名を変更します。その後、作成したPNGファイルをgulp-imageminを使って最適化します。PNG画像はicons.svg
と同じsvg
フォルダに保存します。
gulp.task('svg2png', function () {
gulp.src('svg/icons/*.svg')
.pipe($.svg2png(3))
.pipe($.rename({ prefix: "icons.svg." }))
.pipe($.imagemin())
.pipe(gulp.dest('svg'));
});
4. svg4everbodyの設置
主にIE向けのポリフィルとしてsvg4everybody を設置します。githubからsvg4everybodyをダウンロードしてjs
フォルダに保存します。デモページ ではIE8でテストするためにlegacy版を使いました。
IE9以上のサポート
IE9以上のサポートのみで良い場合は、<head>
に置かなくても良いようです。
<script src="js/svg4everybody.min.js"></script>
<script>svg4everybody();</script>
IE6-8もサポートする場合
IE6-8もサポートする場合、<head>
内でsvg4everybodyを読み込みます。
<script src="js/svg4everybody.legacy.min.js"></script>
<script>svg4everybody();</script>
また、以下を<head>
内に記述します。
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
5. HTMLとCSSの記述
あとはHTMLで以下のように記述すればアイコンを読み込めます。
HTML
#arrow-left
の部分は、ファイル名を指定します。
<svg role="image" class="icon">
<use xlink:href="svg/icons.svg#arrow-left" />
</svg>
CSS
CSSでアイコンの表示サイズや色を指定します。.icon img
では、フォールバックでPNG画像が読み込まれた際のスタイルを指定しています。
.icon {
width: 32px;
height: 32px;
padding: 3px;
border-radius: 4px;
background: #ccc;
fill: #fff;
}
.icon img {
width: 32px;
height: 32px;
padding: 0;
margin: 0;
}
最後に
お疲れさまでした!以上です!
これでアイコン管理が楽になりますね。
と、CSS-Tricksで紹介されている ようにIcomoon のようなサービスを使ってアイコンを管理するのもありだなぁと思って見ていたら、なんとGulpなしでもSVGスプライトを作ってくれるではないですか!しかも、外部SVGファイルの読み込みをサポートするためのIE9-11向けのポリフィル まで用意されてます。。。
あれ??こっちの方が簡単!?笑
次回は、Icomoonを使ったSVGスプライトの作り方をまとめてみたいと思います。。。
他のSVG関連の記事
こちらもご参考までにどうぞ:
- Retina対応にSVGは本当に使えるのか?
- アイコンフォントとアクセシビリティ: ディスレクシア(失読症)向けフォントでの表示問題について
- 1つのSVGスプライト画像をCSS背景画像とインラインHTMLの両方で読み込む方法
- WordPressの投稿でSVG画像を使えるようにしても、OGPやTwitter Cardsで対応してなかった件
参照
主に以下の2つのページでSVGスプライトの手法を学びました。つくづく、この人たちすごいなぁと感嘆するばかりです。いつもありがとうございます!
2015年11月15日に公開され、2016年1月30日に更新された記事です。
About the author
「明日のウェブ制作に役立つアイディア」をテーマにこのブログを書いています。アメリカの大学を卒業後、ボストン近郊のウェブ制作会社に勤務。帰国後、東京のウェブ制作会社に勤務した後、ウェブ担当者として日英バイリンガルのサイト運営に携わる。詳しくはこちら。
ウェブ制作・ディレクション、ビデオを含むコンテンツ制作のお手伝い、執筆・翻訳のご依頼など、お気軽にご相談ください。いずれも日本語と英語で対応可能です。まずは、Mastodon @rriver@vivaldi.net 、Twitter @rriver 、またはFacebook までご連絡ください。
[…] Gulpを使ったSVGスプライトのアイコンシステムとワークフローの作り方 – Rriver […]
[…] Gulpを使ったSVGスプライトのアイコンシステムとワークフローの作り方 – Rriver […]
[…] 以下のサイトを参考にさせていただきました。 Gulpを使ったSVGスプライトのアイコンシステムとワークフローの作り方 GulpでSVGスプライトとアイコン一覧を一発生成 […]