インラインSVG効率化テクニック
こんにちは、AQUARING かに です。
ここ最近はつぶやきProcessingネタの記事ばかりになってしまっていたので、たまにはフロントエンドネタの記事を書こうと思います。
今回はHTMLにSVGタグをインラインで埋め込む際の効率化について紹介します。
インラインSVGについて
基本的には単色アイコンの場合はアイコンフォント化してしまう方がいいので、インラインSVGを採用する際の条件としては「複数色で色のバリエーションがある」または「パーツごとにアニメーションさせたい」場合になります。
なので今回は以下の複数のパーツを持つアイコンを例に説明していきます。
インラインSVGに必要な記述のみにする
イラストレーターでSVG形式で保存すると以下のようにコメントやSVGファイルとして閲覧する際に必要な属性値などが付与されています。
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 40 40" style="enable-background:new 0 0 40 40;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFC61B;}
.st1{fill:#FEE187;}
</style>
<!-- 省略 -->
</svg>
htmlにインライン記述する場合はほとんど必要ないため、必要な属性のみ残して他は消してしまいましょう。
<svg class="svg-star" viewBox="0 0 40 40" width="40" height="40">
<!-- 省略 -->
</svg>
残す属性はviewBoxだけでOKですが、imgタグと同じで何もスタイルを当てないとwidth:100%; に広がってしまうので、width, height を追加してviewBoxと同じ大きさにしておきましょう。
.svg-star .st0 { fill: #FFC61B; }
.svg-star .st1 { fill: #FEE187; }
スタイルはCSSファイルに移動しておきます。
このインラインSVGをそのままコンポーネント化してしまうと、コンポーネントを使うたびに同じSVGの記述が何度もhtmlに出力されることになります。それではhtmlの記述量が無駄に増えてよくないですよね。
そんなときに便利なのが <symbol> です。
SVGシンボルの定義
<svg style="display:none;">
<defs>
<symbol id="svg-star" viewBox="0 0 40 40">
<path class="st0" d="..." />
<polygon class="st1" points="..." />
<!-- 省略 -->
</symbol>
</defs>
</svg>
svg タグの直下に <defs> タグを書き、その中に <symbol> を定義します。
やることは簡単で、さきほどのインラインSVGの <svg> の部分を <symbol>に書き換えるだけです。
<symbol> はテンプレート定義のようなもので、それだけでは実体を持ちません。
あとで参照するために <symbol> には id を設定しておきます。
<symbol> を定義するsvgタグは表示されている必要はないので、display: none; で消しておきましょう。
SVGシンボルの使用
<svg class="svg-star" viewbox="0 0 40 40" width="40" height="40">
<use href="#svg-star" />
</svg>
定義したシンボルを使うときは svg タグの中で <use> の href 属性で <symbol> の id を参照します。
<use> で <symbol> を参照することで、テンプレートのインスタンスを生成して実体化するようなイメージです。
そのまま <symbol> <use> に書き換えるだけではスタイルが効かなくなってしまうので、ちょっと書き換える必要があります。
スタイルの適用方法
<svg class="svg-star" viewbox="0 0 40 40" width="40" height="40">
<use class="st0" href="#svg-star"/>
</svg>
DOM構造の変化によって <symbol> 内にある .st0 などのセレクタが機能しなくなったため、 <use> タグに class をつけることでスタイルを適用できます。
スタイルの適用方法(パーツごと)
<svg style="display:none;">
<defs>
<symbol id="svg-star" viewBox="0 0 40 40" width="40" height="40">
<g id="svg-star-st0">
<path d="..."/>
<!-- 省略 -->
</g>
<g id="svg-star-st1">
<polygon points="..."/>
</g>
</symbol>
</defs>
</svg>
<symbol> <use> にしたうえで複数パーツに別々のスタイルを適用するには、<symbol> の時点でパーツごとに <g> でグループ分けして、それぞれに id をつけ、<use> で個別に参照します。
<svg class="svg-star" viewbox="0 0 40 40" width="40" height="40">
<use class="st0" href="#svg-star-st0"/>
<use class="st1" href="#svg-star-st1"/>
</svg>
パーツごとに分割できてしまえばあとはclassでのカラーバリエーションも作り放題です。
.svg-star.-yellow .st0 { fill: #FFC61B; }
.svg-star.-yellow .st1 { fill: #FEE187; }
.svg-star.-blue .st0 { fill: #1CACFF; }
.svg-star.-blue .st1 { fill: #87D7FF; }
.svg-star.-red .st0 { fill: #FF1C1C; }
.svg-star.-red .st1 { fill: #FF8787; }
参考リンク
<use> - SVG: スケーラブルベクターグラフィック | MDN
defs - SVG: スケーラブルベクターグラフィック | MDN
<symbol> - SVG: Scalable Vector Graphics | MDN
使用したアイコン
この記事が気に入ったらサポートをしてみませんか?