主に技術的なことを書くブログ

浅めにマークアップ&フロントエンドの技術的なことをメモしていましたが、ざっくばらんに書いています。

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本にするだけでだいぶ軽くなりそう。 グループ化しただけになってて気づかなかったりするので注意。

※ 後述していますが、IE9svg単体で背景画像として読み込む場合は、書き出し詳細設定の「レスポンシブ」のチェックを外しておきましょう。

2. Gulp でシンボル化する

jkphl/gulp-svg-sprite

.pipe(svgSprite({
    mode: {
       symbol: true  // Symble化
    }
}))

いろいろ高機能なので、普通にSVGをスプライト画像にすることもできるけど、symbol 形式で書きだしてくれるので、これでバラバラで書きだしたSVGをひとまとめに。

knpwrs/gulp-cheerio

.pipe(cheerio({
    run: function ($, file) {
        $('[fill]').removeAttr('fill');
        $('[stroke]').removeAttr('stroke');
    },
    parserOptions: { xmlMode: true } // これがないと属性が全部小文字になって viewBox が viewbox になる
}))

書きだした sprite.symbol.svgXMLから fill 属性(ベタ色) と stroke 属性(アウトライン色)を消すタスク。 Illustrator の段階で色をCMYK100%にして書き出すと。fill 属性がつかないけど、背景画像で個別に.svgを参照するときに色が黒いので、ベースのアイコンカラーが #000 以外の場合は、このタスクが必要。

parserOptions: { xmlMode: true } を最初つけてなくてドハマリしました。

ben-eb/gulp-svgmin

.pipe(svgmin())

sprite.symbol.svg をミニファイする。

3. HTMLで読み込み

HTML

<svg class="icon">
  <use xlink:href="/images/svg/sprite.symbol.svg#hogehoge" />
</svg>

CSS

.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 要素の対応

github.com

IE10 から条件付きコメントが非対応になっているので、普通に svg4everybody.js を読み込ませます。

IE9svg を単体で背景画像として読み込むときの注意点

background: url('../images/svg/icon_search.svg') 0 0 no-repeat;
background-size: 18px 18px;

input の背景とかに単体の svg を出したい場合、このように background-size を指定すればいけるかとおもいきや、何故か背景画像の要素の幅に応じて、横幅が伸び縮みした。 調べてみると、元の .svgxmlコードに 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 elements with external references when the browser itself fails. This polyfill uses feature detection rather than browser sniffing. It's on github: https://github.com/Keyamoon/svgxuse

引用元:"html5 - SVG use tag with external reference in IE 11 - Stack Overflow

だがしかし、何故か IE9 だけ表示されてなかくてかなりハマって、どうやら、IE9 で表示させるためには、access-control-allow-origin ヘッダ(ドメインをまたいだリソースの参照を許可するやつ)をサーバに設定すればいけるっぽいということで、設定してみたものの表示されないという。。ことで、諦めていました。だれかおしえてください。

参考:JavaScriptプログラミング講座【クロスオリジンリソースシェアリングについて(CORS)】

その他参考:
SVGをIE等のブラウザ対応を考慮して使う方法まとめ(SVGのフォールバック画像など)|2.IDEA
Retina対応にSVGは本当に使えるのか? – Rriver ゲームミュージックと生存確認をかねた画期的な: svgよくやる間違い・まとめ