SVGシンボルスプライト:ID、viewBox、色を保持する
2つのアイコンでSVGシンボルスプライトを作ります。IDとviewBoxを保持し、色の動作、外部参照、使用箇所に合うアクセシブルな名前を確認します。
目次
SVGシンボルスプライトは、一つのSVGファイルに名前付きアイコン定義を格納します。表示する各アイコンは<use>要素で必要な定義を参照します。個別ファイルから移すときにフラグメントID、座標系、塗りの規則が保たれて初めて機能します。
フォルダー全体をまとめる前に、2つのアイコンから始めます。この例では葉は正方形の座標空間、右矢印は横長の空間を使います。葉はパスを複製せず2色で表示し、矢印は葉のキャンバスに押し込まず比率を保持します。
元のアイコンの形、余白、視覚的な太さの統一がまだ必要なら、先にSVGのUIキット準備手順を終えます。スプライトはアートワークを整理するもので、修復はしません。
名前付きのシンボル定義を二つ作る
この独自の例をsprite.svgとして保存します。
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="pv-leaf" viewBox="0 0 24 24">
<path fill="currentColor"
d="M5 19C2 10 9 4 20 4C20 15 14 22 5 19Z"/>
</symbol>
<symbol id="pv-arrow" viewBox="0 0 32 16">
<path fill="currentColor"
d="M2 5H21V1L30 8L21 15V11H2Z"/>
</symbol>
</svg>葉の名前はpv-leaf、矢印はpv-arrowです。ページはこれらの識別子を要求します。MDNはsymbolを、useで具体化する再利用可能なグラフィック定義と説明しています。シンボルだけのファイルは定義を直接描画しないため、単独で開くと空白に見える場合があります。
viewBoxは対応するアートワークと一緒に保持します。ここでは葉が0 0 24 24、矢印が0 0 32 16です。これらは座標範囲であり、必須の表示サイズではありません。形状を調整せずに矢印の範囲を24×24に変えても正規化にはなりません。座標とビューポートの対応はMDNのviewBoxリファレンスを参照してください。
既存のアイコン群には、合意したグリッドを保持します。ここで異なる形を使う目的は別です。まとめる際には、すでに承認した座標系を保持すべきことを示します。線や曲線の端に沿う矢印なら、独自の矢印の位置を揃えるSVGマーカーで接続点と方向を定義します。

ページからスプライトを参照する
sprite.svg、HTMLページ、icons.cssを同じ配信ディレクトリーに置きます。ローカルファイルの制限や別ホストによって基本的な参照ミスが見えにくくならないよう、同一オリジンのHTTPプレビューから始めます。
icons.cssに次の規則を追加し、ページからスタイルシートを読み込みます。
.icon {
display: inline-block;
width: 1.5rem;
height: 1.5rem;
vertical-align: middle;
}
.icon-wide {
width: 3rem;
}
.garden-button {
display: inline-flex;
align-items: center;
gap: 0.5rem;
color: #167d8d;
}次にHTMLのbodyにインスタンスを追加します。
<button class="garden-button" type="button">
<svg class="icon" aria-hidden="true" focusable="false">
<use href="./sprite.svg#pv-leaf"></use>
</svg>
Garden
</button>
<svg class="icon icon-wide" role="img" aria-label="Right direction"
style="color: #233b63">
<use href="./sprite.svg#pv-arrow"></use>
</svg>#の前はファイルの場所、後は選ぶシンボルです。現在の属性はhrefです。MDNのuseリファレンスは外部参照を説明し、ブラウザーがクロスオリジンの読み込みを拒否する場合があると警告しています。動くスプライトをCDNへ移すだけで同じように使えるとは考えず、実際の配信先で試します。
ブラウザーの既定のルート文字サイズでは、この規則は葉に24×24 CSSピクセル、矢印に48×24のボックスを与えます。サイズはremなのでルート文字サイズが異なれば変わります。拡大プレビューと実際のコンポーネント内で比較してください。ボックスが正しくても、アートワークに余白が多すぎる場合があります。
上のボタンはアイコンの表示と名前付けを示しています。製品で使う際は、アプリの操作ハンドラーを追加します。
ファイルをまとめる前に塗りの規則を選ぶ
例の両方のパスは明示的にfill="currentColor"を使います。これによりインスタンスが周囲のCSSのcolorを使えます。ボタンは青緑、矢印は紺色を指定します。colorリファレンスは、currentColorが塗りやストロークの値を提供できると説明しています。
葉を2回目に表示する場合も同じpv-leafを参照し、インスタンスのcolorをサンゴ色に変えます。別のテーマ色を作るためだけにパスを複製しないでください。
| アートワークの意図 | 保持する規則 |
|---|---|
| 単色の塗りのアイコン | 塗るパスに明示的なfill="currentColor"を与えます |
| 単色の輪郭アイコン | 意図したストロークとfill="none"を保持し、どのストロークにcurrentColorを使うか決めます |
| 多色のアートワーク | 承認した固定の塗りを保持するか、選んだ領域を意図的に外から操作可能にします |
| グラデーション | 塗りの定義と、その定義へのすべての参照を一緒に保持します |
多色ロゴのすべての塗りをcurrentColorに置き換えないでください。それは意図的に配色を捨てる操作です。スプライト化の前に色が変わる場合は、SVGの色のトラブルシューティングで先に起きている問題を切り分けます。
任意のページセレクターで参照先のパス内部に届くことを前提にスプライトAPIを作ることも避けます。MDNはuseで複製した内容のスタイル制限を示しています。意図した塗りの動作を元データに組み込み、使用側で試します。
アートワーク内のID重複を防ぐ
シンボル名の一意性は必要ですが、書き出したSVGにはグラデーション、マスク、クリップパスなど、参照される定義のIDもある場合があります。MDNはSVGのidがノードツリー内で一意であることを求めています。別々だった二つのファイルは、結合すると違反する場合があります。
たとえば、葉とバッジの書き出しにどちらもpaint0というグラデーションがあるとします。葉のグラデーションIDと参照の両方に接頭辞を付けます。
| 葉のアートワーク内の場所 | 変更前 | 変更後 |
|---|---|---|
| グラデーション定義 | id="paint0" | id="pv-leaf-paint0" |
| グラデーションを使うパス | fill="url(#paint0)" | fill="url(#pv-leaf-paint0)" |
フラグメントは引き続き目的の定義を指す必要があります。MDNのfillの例は、グラデーションIDとurl(#...)の関係を示します。両方を葉のグラデーションに向けず、バッジには別の接頭辞を付けます。
2パスの例には内部の定義がないため、最初の確認に適しています。実際の書き出しでは、結合前にすべてのIDとローカル参照を洗い出します。最適化ツールや生成ツールの実行後も、配信するスプライトで繰り返します。外側のシンボル名だけ変えても、内部IDの重複は解決しません。
見える各インスタンスに文脈に合う名前を付ける
表示された「Garden」の横の葉は、ボタンがすでに提供する情報を繰り返します。SVGにaria-hidden="true"を付け、ボタンの文字に名前を提供させます。この属性は装飾SVGに付け、操作できるボタンには付けません。MDNのaria-hiddenガイドは装飾内容を扱い、フォーカス可能な要素を隠すことに注意を促しています。
独立した矢印は、近くの文字なしに方向を伝える別の役割があります。外側のSVGはrole="img"とaria-label="Right direction"を使い、MDNの埋め込みSVG画像の名前付けに従います。
ラベルは使用箇所で決めます。再利用する葉は、インターフェースによって「庭」「植物由来」や単なる装飾を意味し得ます。ブラウザーのアクセシビリティ検査ツールと対象の支援技術で、最終コンポーネントのアクセシブルな名前を試します。再利用可能なシンボルだけでは文脈は確定しません。
元ファイルだけでなく配信するスプライトを確認する
この独自の例を同一オリジンのブラウザー検証用ページで確認しました。葉は青緑とサンゴ色で描画され、横長の矢印は形を保持し、意図的に欠けさせたフラグメントは空のアイコンボックスになりました。ブラウザーのアクセシビリティツリーにはGardenボタンと名前付きの矢印が現れました。これはこの検証用ページの確認であり、複数ブラウザーやスクリーンリーダーの認証ではありません。
まとめた後にも同じ小さな確認項目を使います。
- **ファイル:**最終URLから目的のスプライトを読み込んでいることを確認します。
- **フラグメント:**大文字と小文字も含め、各
hrefのフラグメントを配信するシンボルIDと比較します。 - **範囲:**小さなコンポーネントと拡大表示で、切れ、余白、縦横比を比較します。
- **塗り:**単色アイコンを二つのテーマ色で表示し、固定色のアートワークは別に確認します。
- **内部参照:**接頭辞付きの塗り、マスク、クリッピングの参照が最適化後も解決するか確認します。
- **意味:**操作コンポーネントの名前と、意味を持つ独立した画像のラベルを確認します。
ファイルは読み込めるのに一つだけ空白なら、形状を変更する前にフラグメントを調べます。通常のSVGでも空白なら、より広い空白SVGの確認に従います。拡大すると粗く見えるなら、スプライトが原因と考える前に埋め込みラスター画像を調べます。
PNGアイコンしかない場合
単純なアイコンがPNGでしか残っていなければ、まとめる前にPerfectVectorでPNGをSVGへ変換します。シルエット、穴、色領域を元画像と比較し、座標範囲と塗りの規則を承認します。その後、安定したIDを付けてスプライトに追加します。変換はベクターアートワークを提供しますが、シンボル名、コンポーネントの意味、配信設計は選びません。
整理された元のSVGがあれば使います。再トレースは形を復元する手順を増やすだけで、壊れたフラグメント参照を解決しません。残った問題が格納方法ではなくアートワークにあるなら、SVG編集と準備のガイドを参照してください。
よくある質問
スプライトを直接開くと空白なのはなぜですか? シンボル定義だけのスプライトは、そのシンボルを直接表示しません。壊れたアートワークと考える前に、正しいファイルパスとフラグメントIDを使うSVGのuseインスタンスで試してください。
すべてのシンボルに同じviewBoxが必要ですか? いいえ。まとめる際は承認した各座標系を保持します。同じデザインシステムのグリッドを共有するアイコンは同じ範囲を使えますが、横長のシンボルはviewBoxの値を変えただけで正方形のアイコンにはなりません。
ページの色を変えてもアイコンの色が変わらないのはなぜですか? 元の塗りの規則を確認します。固定の塗りはcurrentColorで作ったパスと異なります。意図した多色アートワークは保持し、インスタンスの色を継承する塗りやストロークを明示的に選びます。
別ドメインにスプライトを置けますか? 外部use参照が異なるオリジンでも動くとは考えないでください。同一オリジンの検証用ページから始め、配信を変える前に実際のホストと対象ブラウザーで試します。ローカルの成功例はクロスオリジン対応を証明しません。
参考資料
- MDN — symbol — 再利用可能な定義と間接的な描画。
- MDN — use — 外部フラグメント、スタイル制限、オリジン制限。
- MDN — viewBox — 座標範囲とビューポートの関係。
- MDN — color — SVGの塗りへの入力としてのcurrentColor。
- MDN — id — 文書ツリー内の識別子の一意性。
- MDN — fill — グラデーションURLなどの塗りの参照。
- MDN — aria-hidden — 装飾内容とフォーカス可能な要素への注意。
- MDN — imgロール — 意味のある画像に使う、ラベル付きの外側SVG。
承認した2つのアイコンから始め、実際のコンポーネントで名前、範囲、色を試します。一つの元データが適したラスターでしか存在しないなら、SVGパスを復元し、アートワークを確認してから採用結果をスプライトに追加します。
