SVGスプライトは複数の画像を一つのファイルにまとめたもの。表示時に画像をid
指定するため複数ヶ所で参照する時に短く書けて画像やHTMLファイルのサイズが削減できる。
成果物
- インライン版
- 外部参照版
インライン版
サーバ不要。
index.html
<svg> <defs> <symbol id="clipboard" viewBox="0 0 256 256"><path d="M64 0a8 8 0 0 0-8 8v16H32a8 8 0 0 0-8 8v216a8 8 0 0 0 8 8h192a8 8 0 0 0 8-8V32a8 8 0 0 0-8-8h-24V8a8 8 0 0 0-8-8zm8 16h112v48H72V32zM40 40h16v32a8 8 0 0 0 .041.799 8 8 0 0 0 .12.79 8 8 0 0 0 .472 1.526 8 8 0 0 0 .765 1.403 8 8 0 0 0 .485.636 8 8 0 0 0 1.144 1.114 8 8 0 0 0 1.346.863 8 8 0 0 0 .729.326 8 8 0 0 0 1.54.426A8 8 0 0 0 64 80h128a8 8 0 0 0 1.59-.16 8 8 0 0 0 1.525-.473 8 8 0 0 0 .72-.347 8 8 0 0 0 .682-.418 8 8 0 0 0 2.215-2.28 8 8 0 0 0 .977-2.183 8 8 0 0 0 .29-2.14V40h16v200H40z"/></symbol> <symbol id="file" viewBox="0 0 256 256"><path d="M32 0a8 8 0 0 0-8 8v240a8 8 0 0 0 8 8h192a8 8 0 0 0 8-8V72a8 8 0 0 0-.006-.125 8 8 0 0 0-.021-.39 8 8 0 0 0-.032-.405 8 8 0 0 0-.056-.373 8 8 0 0 0-.076-.42 8 8 0 0 0-.09-.35 8 8 0 0 0-.121-.423 8 8 0 0 0-.131-.356 8 8 0 0 0-.153-.383 8 8 0 0 0-.171-.357 8 8 0 0 0-.182-.348 8 8 0 0 0-.219-.357 8 8 0 0 0-.213-.324 8 8 0 0 0-.242-.319 8 8 0 0 0-.25-.31 8 8 0 0 0-.38-.416l-.085-.082-63.916-63.918a8 8 0 0 0-.049-.045 8 8 0 0 0-.27-.244 8 8 0 0 0-.32-.284 8 8 0 0 0-.351-.257 8 8 0 0 0-.291-.207 8 8 0 0 0-.365-.22 8 8 0 0 0-.33-.187 8 8 0 0 0-.457-.213 8 8 0 0 0-.25-.11 8 8 0 0 0-.48-.169 8 8 0 0 0-.288-.096 8 8 0 0 0-.447-.105 8 8 0 0 0-.338-.076 8 8 0 0 0-.422-.059 8 8 0 0 0-.37-.045A8 8 0 0 0 160 0zm8 16h112v56a8 8 0 0 0 .041.799 8 8 0 0 0 .94 3.037 8 8 0 0 0 .417.682 8 8 0 0 0 2.28 2.214 8 8 0 0 0 2.965 1.15A8 8 0 0 0 160 80h56v160H40zm128 11.312L204.688 64H168z"/></symbol> <defs> </svg> <svg><use href="#clipboard"></use></svg> <svg><use href="#clipboard"></use></svg> <svg><use href="#file"></use></svg> <svg><use href="#file"></use></svg>
画像データは以前作成したSVG画像をコピペして作った。
外部参照版
- sprite.svg
- index.html
sprite.svg
<svg xmlns="http://www.w3.org/2000/svg"> <defs> <symbol id="clipboard" viewBox="0 0 256 256"><path d="M64 0a8 8 0 0 0-8 8v16H32a8 8 0 0 0-8 8v216a8 8 0 0 0 8 8h192a8 8 0 0 0 8-8V32a8 8 0 0 0-8-8h-24V8a8 8 0 0 0-8-8zm8 16h112v48H72V32zM40 40h16v32a8 8 0 0 0 .041.799 8 8 0 0 0 .12.79 8 8 0 0 0 .472 1.526 8 8 0 0 0 .765 1.403 8 8 0 0 0 .485.636 8 8 0 0 0 1.144 1.114 8 8 0 0 0 1.346.863 8 8 0 0 0 .729.326 8 8 0 0 0 1.54.426A8 8 0 0 0 64 80h128a8 8 0 0 0 1.59-.16 8 8 0 0 0 1.525-.473 8 8 0 0 0 .72-.347 8 8 0 0 0 .682-.418 8 8 0 0 0 2.215-2.28 8 8 0 0 0 .977-2.183 8 8 0 0 0 .29-2.14V40h16v200H40z"/></symbol> <symbol id="file" viewBox="0 0 256 256"><path d="M32 0a8 8 0 0 0-8 8v240a8 8 0 0 0 8 8h192a8 8 0 0 0 8-8V72a8 8 0 0 0-.006-.125 8 8 0 0 0-.021-.39 8 8 0 0 0-.032-.405 8 8 0 0 0-.056-.373 8 8 0 0 0-.076-.42 8 8 0 0 0-.09-.35 8 8 0 0 0-.121-.423 8 8 0 0 0-.131-.356 8 8 0 0 0-.153-.383 8 8 0 0 0-.171-.357 8 8 0 0 0-.182-.348 8 8 0 0 0-.219-.357 8 8 0 0 0-.213-.324 8 8 0 0 0-.242-.319 8 8 0 0 0-.25-.31 8 8 0 0 0-.38-.416l-.085-.082-63.916-63.918a8 8 0 0 0-.049-.045 8 8 0 0 0-.27-.244 8 8 0 0 0-.32-.284 8 8 0 0 0-.351-.257 8 8 0 0 0-.291-.207 8 8 0 0 0-.365-.22 8 8 0 0 0-.33-.187 8 8 0 0 0-.457-.213 8 8 0 0 0-.25-.11 8 8 0 0 0-.48-.169 8 8 0 0 0-.288-.096 8 8 0 0 0-.447-.105 8 8 0 0 0-.338-.076 8 8 0 0 0-.422-.059 8 8 0 0 0-.37-.045A8 8 0 0 0 160 0zm8 16h112v56a8 8 0 0 0 .041.799 8 8 0 0 0 .94 3.037 8 8 0 0 0 .417.682 8 8 0 0 0 2.28 2.214 8 8 0 0 0 2.965 1.15A8 8 0 0 0 160 80h56v160H40zm128 11.312L204.688 64H168z"/></symbol> <defs> </svg>
index.html
<svg><use href="./sprite.svg#clipboard"></use></svg> <svg><use href="./sprite.svg#clipboard"></use></svg> <svg><use href="./sprite.svg#file"></use></svg> <svg><use href="./sprite.svg#file"></use></svg>
HTTPS server
上記のように外部のSVGファイルを参照する場合はHTTPSサーバを立てる必要がある。
SVGスプライト作成
以下のようなフォーマットになる。
<svg xmlns="http://www.w3.org/2000/svg"> <defs> <symbol id="..." viewBox="0 0 256 256"><path d="..."/></symbol> <defs> </svg>
要素 | 概要 |
---|---|
<svg> |
SVGルート要素 |
<defs> |
定義要素を含める |
<symbol> |
id 属性値に識別名を記入する |
<path> |
d 属性値にパスデータを記入する |
- 画像一つあたりの要素を
<symbol>
に入れる - 1の
id
属性値に識別子をつける - 画像の数だけ上記を繰り返す
ポイントは以下。
<defs>
により、その内容が<use>
で参照すべきものであることを示す(表示内容でないことを示す)<symbol>
により、その内容を<use>
するとき、<use>
で属性指定することで変更可能になる(色やサイズ等)<path>
はInkscape等で作成した要素そのままコピペする
尚、そのまま挿入されると空白領域が表示されてしまうため、以下のいずれかで非表示にする。
<svg style="display:none;">
<svg width="0" height="0">
SVGスプライト利用
<svg><use href="..."></use></svg>
href
にはpath#id
の形式で与えるpath
はファイルパスid
はSVGスプライトで定義した属性値
注意点はid
が必須であること。また、インラインの場合、他の要素とid
が重複しやすくなる。
変更
- 色
- サイズ
色
index.html
<svg> <use href="..." fill="#f00"/> </svg>
fill
やstroke
で色をセットする
CSSで調整してもいい。
<style>.icon{fill:#f00; stroke:#0f0;}</style> <svg css="icon"> <use href="..."/> </svg>
属性 | 意味 |
---|---|
fill |
内側の塗りつぶし色 |
stroke |
外側(輪郭)の色 |
fill:none
にすると塗りつぶしが失くなり、マウスイベントまで失う。
サイズ
viewBox
width
height
<symbol>
でviewBox
を定義し、d
でそれに応じた図形を作る。それを<use>
で参照し、その大きさは<use>
をもつ<svg>
のwidth
,height
で指定する。viewBox
はそれに合わせて拡縮する。
sprite.svg
... <symbol id="..." viewBox="0 0 256 256"><path d="..."/></symbol> ...
index.html
<svg width="1em" height="1em"> <use href="..."/> </svg>
CSSでセットしてもいい。
<style>.icon{width:1em; height:1em;}</style> <svg class="icon"> <use href="..."/> </svg>
属性 | 意味 |
---|---|
viewBox |
図形パス座標はこの領域内に含めること |
width , height |
実際の表示サイズ。viewBox はこの領域内に収まるよう拡縮する |
SVGスプライトの使い所は?
SVGスプライトを使うべき場面はいつ? SVG画像そのままでもいいのでは? わざわざスプライトにする必要ある?
こうした疑問には、次の効果があると答える。
- 通信量を減らす
- ファイル容量を減らす
- 製作コストを減らす
通信量を減らす
以下によると複数のSVG画像を一つのSVGスプライトファイルにまとめることでHTTP通信の回数を減らし応答速度を改善してきたという。今となっては通信技術により、その必要がないという話のようだが。
HTTP通信数を減らす方法 | 概要 |
---|---|
スプライティング | 複数の画像を一つにまとめる |
インライニング | 画像をBase64化しCSSに埋め込む |
コンカチネーション | JSファイルを全て1つにまとめる |
HTTP ver | 概要 |
---|---|
1.1 | オーバーヘッドがあり通信やキャッシュの効率が悪い |
2.0 | 通信の多重化(並列処理により通信回数が増えても良くなった) |
3.0 | QUICによりHead-of-Line-Block問題解決 |
ただ、SVGスプライトが役目を終えたわけではない。上記の記事はあくまでHTTP通信頻度を下げる工夫としてのスプライティングという手法はHTTP2以降の通信技術により不要化する、と言っているだけだと思う。わざわざ一つのファイルにまとめずとも、複数のSVG画像でそれぞれHTTPリクエストしても、HTTP2以降なら通信回数がファイル数の分だけ増えても問題なくなった、という話に過ぎない。
SVGの価値はファイルを一つにまとめてHTTPリクエスト回数を減らすだけではない。
制作コスト・ファイル容量を減らす
SVGスプライトの価値は他にもある。制作コストとファイル容量を減らせる点だ。
同じ図形を短縮参照し、それぞれに拡縮・変色・変形などの幅広い変化をつけて流用できる。これにより、ゼロから色やサイズ等が違うだけの図形を複数作成してそれぞれ異なるパスデータを持たせるよりもファイル容量が縮小できる。そういう使い方をするのがSVGスプライトの本領であり価値だろう。その価値は未だ衰えず、替えの効かないSVGスプライトの存在意義だと思う。
以下のサイトでは単一の図形を複数参照して、角度などを変えて配置し一つの図形を作成している。
応用はいくらでも思いつく。たとえば矢印を一つ作って、それを4つ参照し、それぞれ別の角度をつけてやれば、一つの基礎画像で四つの矢印が作れる。これは四つの画像ファイルを別の図形データとして作るよりも制作の手間やファイル容量が少なく済む。ファイル容量が減れば、そのままHTTP通信量の削減にもなる。
もちろん矢印は他の図形とも組合せ可能なので、いくらでも流用できる。流用の回数が増えるほどファイル縮小効果があがる。
というわけで、SVGスプライトはパフォーマンスの観点から見ても、制作工程を減らす観点から見ても、学ぶべき価値のある技術のはずだ。そうしたファイル作成を想定し実装することで劇的に容量削減できる可能性を持っている。学習コストも高めだが、その価値はあるだろう。流用する最低限の知識として、<defs>
, <symbol>
, <use>
を知っておけば充分だ。
まとめ
- アイコンを作る
- それを
<use>
で組合せる or 複数ヶ所で参照する - 繰り返す
これにより以下が改善される。
- アイコン作成の労力
- ファイルサイズ
- HTTP通信量
SVGスプライト、すごい、えらい、つよい。