color-mix()関数でCSS変数とrgba()の表現を共存させよう!

color-mix()関数でCSS変数とrgba()の表現を共存させよう!

こんにちは。3年目のユーヤです。

今回のブログは、コーディングに便利なCSS変数についてのお話です。

長めの前置き

Adobe XDのサポートが終了してもう1年が経とうとしていますね。弊社でもデザインツールがfigmaに移行して、コーディング時にスタイルやらテキストやらを直接コピーできる便利さに甘え切ってしまっているのですが、あるとき問題が発生してしまったのです。

というのも、複数パターンがあるパーツの色指定にCSS変数を使っていたのですが、背景色に透明度が指定されているけど中に別の要素が入るからopacityは使えない、といったパーツでSassのrgba($color, $alpha)を使って半透明な色指定をしようとしたのです。ところが出力を見ると色が出ていませんでした。検証ツールで見ると、

background-color: rgba(#ddd, 0.7);

となっていました(数値は仮に色を#ddd、透明度を0.7としています。)。本来であれば、コンパイル時にHex値からrgb値に変換されて

background-color: rgba(221, 221, 221, 0.7);

とならなければなりません。どうやらCSS変数で指定したカラーコード#dddが文字列として処理されてしまっているようです。

これは、Sass関数とCSS変数の評価タイミングの違いによるものです。
Sass関数はCSSへのコンパイル前に実行されますが、CSS変数はコンパイル後、ブラウザ上で表示されるタイミングで値が評価されます。つまり…

(scss)background-color: rgba($color: var(--mainColor), $alpha: 0.7);
↓コンパイル
(CSS)background-color: rgba(var(--mainColor), 0.7);
↓CSS変数に値を代入
(ブラウザ上)background-color: rgba(#ddd, 0.7);

というわけです。ですので、どんなに頑張ってもSass関数にカラーコードのCSS変数は使えない、ということになります。

これを回避するには、Sass関数ではない方法で記述する必要があります。

たとえば、上にもあるCSSのrgba()関数や、色相(Hue)、彩度(Saturation)、明度(Lightness)を指定するhsla()関数が挙げられます。

しかし、これらはそれぞれ色を3つの値で決定するためCSS変数を3つに分ける、ないし3つまとめて指定する必要があります。ですがせっかくHex値でコピーしてきた色を毎回rgb値やhsla記法に改めるのは手間がかかって仕方ないでしょう。

そこで、今回の本題であるcolor-mix()関数が使えるというわけです!

本題

まずはcolor-mix()関数について。

color-mix() 関数記法は 2 つの 値を採り、指定された色空間の指定された量で混合した結果を返します。

https://developer.mozilla.org/ja/docs/Web/CSS/Reference/Values/color_value/color-mix

簡単に言えば、2つの色を混ぜて出力するということです。

記法は以下のようになっています。

color-mix(method, color1[ p1], color2[ p2])

methodは色補間に使用する色空間を指定しますが、これは自動入力で出てくるsrgbで問題ないようです。
color1とcolor2はそれぞれ混合する色、p1とp2はそれぞれのcolorのパーセンテージです。

詳細な解説はMDNのページをご覧ください。

https://developer.mozilla.org/ja/docs/Web/CSS/Reference/Values/color_value/color-mix

今回出力したい–mainColor: #ddd;、opacity: 0.7;を当てはめると、

background-color: color-mix(in srgb, var(--mainColor) 70%, transparent);

となります。p1・p2は片方を省略した場合は100%からもう片方を引いた値が割り振られるのでtransparent側の透明度を指定する必要はありません。

実際に指定したサンプルがこちらです。

See the Pen color-mix() by NP-Kanbara (@elmhgegi-the-solid) on CodePen.

CSS変数とcolor-mix()で指定した場合と、Sass関数rgba()で指定した場合で同じ結果を得られていることがわかりますね!

おわりに

CSS変数は取り回しの良さが魅力なので、こうして様々なパターンに対応できると嬉しいですね!

ではまた。