先に結論
前提
主にhoverで色が変わるボタンなどで、疑似要素でアイコンを配置するときの話です。
アイコンの部分を除くと、以下のようなCSSになっていると仮定します。
.button{
display: inline-flex;
align-items: center;
gap: 16px;
background: #0A246A;
color: #fff;
padding:20px;
line-height: 1.5;
text-decoration: none;
transition: background-color 1s, color 1s;
}
.button:hover{
background: #fff;
color: #0A246A;
}
従来
アイコン部分はbackgroundで画像を配置して、hover時のCSSで別の画像に切り替えます。
ただbackground-imageのtransitionはブラウザによって微妙に効いたり、微妙に効かなかったり、全然効かなかったり……
Chrome126ごろ:アイコンのtransitionが効いていたり効いていなかったりする様子
.button::after{
content: "";
width: 16px;
height: 16px;
background: url("chevron-white.svg") no-repeat center / contain;
transition: background-image 1s;/* chromeでは微妙に効く */
}
.button:hover::after{
background: url("chevron-blue.svg") no-repeat center / contain;
}
今はこれでOK
backgroundの代わりにmaskを指定すれば、画像は1枚でいいし、hover用のCSSも基本不要です。
この方法ならtransitionに悩まされることも無し。
※iOS15.4からは-webkit-
いらなくなりました。
Can I Use…
.button::after{
content: "";
width: 16px;
height: 16px;
background: currentColor;/*文字色とアイコンの色が一致するならこれでOK*/
mask: url("chevron.svg") no-repeat center / contain;
}
maskの詳細
まずアイコンを表示に使う::afterのサイズを決めて、アイコンの色をbackgroundとして指定します。
多くの場合はテキストの色と同様になるためcurrentColor
を指定しておきます。(そうすることで:hover::afterの色を指定が不要になります)
.button::after{
content: "";
width: 16px;
height: 16px;
background: currentColor;/*文字色とアイコンの色が一致するならこれでOK*/
}
※display:inline-flexの中に配置しているため、display:blockを指定しなくてもwidth等が指定できます。
すると、アイコンを配置したい位置に、四角形が表示されます。
次に、アイコン画像を用意します。
色は黒でも白でもなんでも良いし、SVGでもPNGでも構いません。
最後にアイコン画像をmask: url("chevron.svg") no-repeat center / contain;
のように指定します。
プロパティ名以外はbackgroundに画像を指定するときと同じです。
.button::after{
content: "";
width: 16px;
height: 16px;
display: block;
background: currentColor;/*文字色とアイコンの色が一致するならこれでOK*/
mask: url("chevron.svg") no-repeat center / contain;
}
これで、アイコンが表示されました。
この方法のよいところ:CSSのみで色を変更できる
この方法だとアイコンの色は疑似要素のbackground-colorになるため
- background-colorはtransitionが効く
- 何色あっても画像は1ファイルでよい
というメリットがあります。
この方法では対応できないパターン:アイコン内で複数色を使う
もしもアイコンがカラフルで一度に複数色を表現する場合は、maskでは表現できません。
まとめ
単色のアイコンかつ、サイト内でいろいろな色(hover前後など)で使う場合はmaskを利用して効率よく変更に強い実装試してみましょう!
コメント