SVG画像で作る汎用的で使い回しやすいアイコンポーネント
他のサイトのソースコードを眺めていて、「これいいな」と思ったアイコンコンポーネントの作成方法を紹介しています。この方法が便利すぎて最近のコーディングでは必ずと言っていいほど使用しています。
アイコンコンポーネントの作成例
早速ですが以下が作成例です。
<span class="c-icon" data-c-icon="arrow" aria-hidden="true"></span>.c-icon { display: block; width: 100%;}
.c-icon::before { content: ""; width: 100%; display: block; background-color: currentColor; mask-position: center; mask-repeat: no-repeat; mask-size: contain;}
.c-icon[data-c-icon="arrow"]::before { aspect-ratio: 1; /* アイコンの縦横比を記述 */ mask-image: url(../img/common/icon_arrow.svg); /* アイコン画像へのパスを記述 */}アイコンを表示するためのspanタグを用意し、アイコン自体はspanタグの擬似要素で表示しています。
使い方
例えば矢印のアイコンを表示したい場合には、HTMLの表示したい箇所に以下のように記述します。data-c-icon="アイコン名"の箇所で、表示するアイコンを指定します。
<span class="c-icon" data-c-icon="arrow" aria-hidden="true"></span>アイコンは多くのケースで装飾的な要素のため、スクリーンリーダーから隠すためにaria-hidden="true"を追加しています。
CSSではベースとなる記述に加えて、矢印のアイコンに関連するコードを記述しています。
.c-icon[data-c-icon="arrow"]::before { aspect-ratio: 1; /* アイコンの縦横比を記述 */ mask-image: url(../img/common/icon_arrow.svg); /* アイコン画像へのパスを記述 */}表示したいアイコンの種類が増えた場合には、CSSにその都度コードを追加するイメージです。基本的にはアイコンごとにaspect-ratioとmask-imageを追加すれば機能します。mask-imageでSVGをマスク画像として使い、background-colorで塗りつぶすことでアイコンを表示する仕組みです。
ラッパー要素で囲って、親要素側でアイコンのサイズを管理すると汎用性が高まります。
<div class="arrow-icon"> <span class="c-icon" data-c-icon="arrow" aria-hidden="true"></span></div>.arrow-icon { display: flex; width: 50px;}メリット
この方法のメリットをいくつか挙げてみます。
メンテナンス性の向上
アイコンの追加・変更が.c-icon[data-c-icon="アイコン名"]のパターンで統一的に行えるため、保守・管理が行いやすくなります。またSVGのパスを直接HTMLに書く場合と比べて、HTMLがシンプルに保たれ、可読性が向上します。
柔軟な拡張性
currentColorを使用することで、色を親要素やスタイルのコンテキストに従わせることができます。hover時の色変更のアニメーションやダークモード対応などへの柔軟性が高まります。
例えばアイコンの色を変えたい場合は次のように、colorプロパティを使用して変更することができます。
.c-icon[data-c-icon="arrow"] { color: var(--primary-color); /* プライマリーカラーに色を変更 */}ファイルサイズの最適化
SVGファイルを外部化することで、同じアイコンが複数箇所で使用される場合でもキャッシュを活用することが可能です。
またHTMLにSVG画像をインラインで記述する場合と比べて、HTMLのファイルサイズを小さく保つことができます。大量のインラインSVGを使う場合には特に効果が大きいでしょう。
注意点
実務で使う上で注意すべき点が2点あります。
複雑なマルチカラーSVGへの対応
複雑なマルチカラーのSVGにはこの方法は適していません。
mask-imageをbackground-imageに変更することでアイコンを表示することは可能ですが、今回の方法のメリットであるcurrentColorによる色制御ができなくなるので注意が必要です。
ブラウザサポート状況
mask-imageは記事執筆時点(2025年1月)ですべての主要ブラウザで対応が完了しています。詳細なブラウザサポート状況はCan I Use をご確認ください。
必要に応じて-webkit-mask-imageなどのベンダープレフィックスを追加することをご検討ください。
まとめ
メリットの多い方法なので今後も積極的に活用していこうと思います。テンプレート等のベースとなるファイルに今回のコードを記述しておけば、多くのプロジェクトにおいて使い回せそうです。
