CSSでアイコンを実装するとき、こんなことありませんか?
- アイコンの色を hover ごとに指定している
- テキストとアイコンの色がズレる
- SVGの色変更が地味につらい
- アイコンが増えるたびにCSSが肥大化する
私はずっと「まあ、こんなもんか…」と思っていました。
が、currentColor を発見して、実装がスッキリしました。
今回やりたかったこと
今回やりたかったのは、こんな仕様です。
- テキストの前にアイコンを表示したい
- アイコンはSVG(単色)
- アイコンの色はテキスト色と連動させたい
- data属性でアイコン種別を切り替えたい
- 将来WordPress化しても壊れない設計にしたい
完成形のコード(先に見せる)
[data-icon] {
display: inline-flex;
align-items: center;
gap: 18px;
&::before {
content: '';
display: block;
width: 26px;
aspect-ratio: 1 / 1;
background: currentColor;
-webkit-mask: center / contain no-repeat;
mask: center / contain no-repeat;
}
}
$icons: download, mail, seminar, document, blank;
@each $icon in $icons {
[data-icon="#{$icon}"]::before {
-webkit-mask-image: url("../img/common/icon_#{$icon}.svg");
mask-image: url("../img/common/icon_#{$icon}.svg");
}
}
[data-icon="blank"]::before {
display: none;
}
<a data-icon="download">資料ダウンロード</a>
<a data-icon="mail">お問い合わせ</a>
など
currentColor とは何か
currentColor は、その要素の color の値を参照するCSSキーワードです。
つまり、
- テキストの色
- 枠線の色
- 背景色
- maskで使う塗り色
を 1つの color 指定でまとめて制御できます。
mask × currentColor が強い理由
SVGを mask として使うと、SVGは「形」だけを担当します。
実際の色は background で付けるため、currentColor がそのまま使えます。
&::before {
background: currentColor;
mask: center / contain no-repeat;
}
得られるメリット
- hover時に color を変えるだけ
- ダークモードも color 切り替えだけ
- デザイン変更が一瞬
data-icon × SCSSループの良さ
アイコンの切り替えは data属性で行います。
CSS側では SCSS の @each を使ってまとめて定義します。
$icons: download, mail, document;
@each $icon in $icons {
[data-icon="#{$icon}"]::before {
mask-image: url("../img/common/icon_#{$icon}.svg");
}
}
なぜ良いか
- $iconsにアイコン名を追加するだけでいいのが◎
- JS不要
- 将来の拡張が楽
- WordPress + ACFも相性がいい(ACFの select で icon 名を管理する、とか)
まとめ
- currentColor は「今の文字色」
- mask と組み合わせるとアイコン実装が一気に楽になる
- data-icon × SCSSループで拡張性も高い
- CSS設計をちゃんとすると、将来の自分が助かる
- PR