SVGシンボル化(SVGスプライト)
けっこう前ですが、GitHub のアイコンがアイコンフォントからSVGアイコンにすべて変わりました。(GitHubではここで書いてある方法ではなく個別でベタ書きですが) Delivering Octicons with SVG · GitHub
そろそろアイコンファイルの主流はSVGになりつつあるのかなぁ、と思っています。
スプライトというと、画像をいっぱいまとめて並べて、background-position で表示みたいなイメージになりがちですが、SVGの場合、ラスタライズしてしまうと全く良さがなくなるので、シンボル化、という方法で、スプライト画像のメリット=ファイルをひとつにまとめて画像リクエストの回数を減らす、さらに svg アイコンのメリット = fill 属性で css で色変更、ということを達成できます。
1. Illustrator でつくった SVGアイコンをバラバラで書き出す
書き出し方はこちらが参考になる www.webcreatorbox.com d.hatena.ne.jp
パスを全部複合パスにして、1本にするだけでだいぶ軽くなりそう。 グループ化しただけになってて気づかなかったりするので注意。
※ 後述していますが、IE9で svg を単体で背景画像として読み込む場合は、書き出し詳細設定の「レスポンシブ」のチェックを外しておきましょう。
2. Gulp でシンボル化する
.pipe(svgSprite({ mode: { symbol: true // Symble化 } }))
いろいろ高機能なので、普通にSVGをスプライト画像にすることもできるけど、symbol 形式で書きだしてくれるので、これでバラバラで書きだしたSVGをひとまとめに。
.pipe(cheerio({ run: function ($, file) { $('[fill]').removeAttr('fill'); $('[stroke]').removeAttr('stroke'); }, parserOptions: { xmlMode: true } // これがないと属性が全部小文字になって viewBox が viewbox になる }))
書きだした sprite.symbol.svg のXMLから fill 属性(ベタ色) と stroke 属性(アウトライン色)を消すタスク。 Illustrator の段階で色をCMYK100%にして書き出すと。fill 属性がつかないけど、背景画像で個別に.svgを参照するときに色が黒いので、ベースのアイコンカラーが #000 以外の場合は、このタスクが必要。
parserOptions: { xmlMode: true } を最初つけてなくてドハマリしました。
.pipe(svgmin())
sprite.symbol.svg をミニファイする。
3. HTMLで読み込み
HTML
<svg class="icon"> <use xlink:href="/images/svg/sprite.symbol.svg#hogehoge" /> </svg>
.icon { width: 20px; height: 20px; fill: red; }
このままだと、useタグで別ファイルを読む込むのが IE と 古いEdge(今はサポートされてる)でサポートされてないらしい。
当たり前のことであるが,クロスドメインでのsvgファイルの参照は無効である.また,ie9においてはuse要素による外部svgファイルの参照ができないので注意が必要となる.
引用元:"svg要素の基本的な使い方まとめ
MS Edgeでのサポート
Edge Dev のMSEdge on Win10 (Edge 20.10240.6384.0)で確認したところ、表示されませんでした。Edgeではuseを使った外部ファイルの読み込みがサポートされていないようなのですが、11月にリリースされたBuild 10586のEdgeHTML 13で機能が実装された とのことです。
引用元:"Gulpを使ったSVGスプライトのアイコンシステムとワークフローの作り方 – Rriver
4. svg4everybody をつかって、IE9 以上で use 要素の対応
IE10 から条件付きコメントが非対応になっているので、普通に svg4everybody.js を読み込ませます。
IE9で svg を単体で背景画像として読み込むときの注意点
background: url('../images/svg/icon_search.svg') 0 0 no-repeat; background-size: 18px 18px;
input の背景とかに単体の svg を出したい場合、このように background-size を指定すればいけるかとおもいきや、何故か背景画像の要素の幅に応じて、横幅が伸び縮みした。 調べてみると、元の .svg の xmlコードに width と height 指定がないとそうなるという感じらしく。
Be sure that your SVG has a width and height specified. If you're generating it from Illustrator, ensure that the "Responsive" box is unchecked as this option removes width and height.
引用元:"css - Background-size with SVG squished in IE9-10 - Stack Overflow
IE9 対応する場合は、Illustrator の書き出し時に、レスポンシブのチェックを外しておかないといけないです。
4. svg4everybody から svgxuse に乗り換えてみる
svg4everybody でしばらく様子見していたのですが、時々、読み込まれない時があってモヤモヤしてたので、svgxuse という別のやつに乗り換えてみました。
svg4everybody uses requestAnimationFrame, which causes too many calls. I wrote a simple and lighweight polyfill for the very purpose of supporting
だがしかし、何故か IE9 だけ表示されてなかくてかなりハマって、どうやら、IE9 で表示させるためには、access-control-allow-origin ヘッダ(ドメインをまたいだリソースの参照を許可するやつ)をサーバに設定すればいけるっぽいということで、設定してみたものの表示されないという。。ことで、諦めていました。だれかおしえてください。
参考:JavaScriptプログラミング講座【クロスオリジンリソースシェアリングについて(CORS)】
その他参考:
SVGをIE等のブラウザ対応を考慮して使う方法まとめ(SVGのフォールバック画像など)|2.IDEA
Retina対応にSVGは本当に使えるのか? – Rriver
ゲームミュージックと生存確認をかねた画期的な: svgよくやる間違い・まとめ