以前、色の濃度を変えるにはSassのmix
が便利だね、という記事を書きました。

私も今ではIllustratorのデザインデータでコーディングすることも少なくなりましたが、先日、当時の案件の修正を行なっていたところ、mix
関数辺りに異変が起きていました。
2025年現在のSassのmixモジュールの使い方を、改めて検証してみます。
起きていた異変
数年前に制作したWebサイトのSassを更新し、コンパイルを行ったところ、以下のようなエラーが。
Warning:
Global built-in functions are deprecated and will be removed in Dart Sass 3.0.0.
Use color.mix instead.
そのまま翻訳してみます。
警告:
グローバル組み込み関数は非推奨であり、Dart Sass 3.0.0 で削除されます。
代わりに color.mix を使用してください。
mix
は組み込み関数として使用していましたが、Dart Sass v3ではビルトインモジュールとして使用することになったようです。
そこで、書き方を以下のように変更すると、無事コンパイルできるように。
※詳細や経緯は前述の記事をご確認ください
//Before
//関数の設定
@function colorMix($color, $percent) {
@return mix($color, #fff, $percent * 1%);
}
これを、こう。
//After
@use "sass:color"; //追加
//関数の設定
@function colorMix($color, $percent) {
@return color.mix($color, #fff, $percent * 1%); //「color.mix」表記に変更
}
解決、解決ぅ♪とルンルンでコンパイルされたコードの差分チェックを行うと、新たな異変が。
以前はカラーコード(16進数 / HEX / #XXXXXXの形式)で出力されていたはずのCSSが、なぜかrgb()形式で出力されていました。
しかも、小数点という細かい数値で。

mixの出力形式が変わってしまった原因
どうやら、Dart Sass v3 の color.mix()
の結果は「内部的に計算した色」をそのまま出すので、#fccのような16進数ではなく rgb()
形式で出力されることがあるとのこと。
これは仕様であって、color.mix()
側に「16進数で出力する」というオプションはない模様。
公式ドキュメントによると、$methodで色空間を指定できるそうなのですが、私の場合は結果は同じでした。
@use ‘sass:color’;
Sass: sass:color
@debug color.mix(#036, #d2e1dd, $method: rgb); // #698aa2
rgb()
のままでも正確であれば良いのですが、やはり保守はしにくいなぁということで、HEX形式で出力できるようにしてみました。
color.mix() の結果をHEX形式で出力する
もちろん、color.mix()
だけでは出力できないので、自前で hex 文字列に変換する関数を作ってみます。
具体的な処理はこんな感じ。
- 以前のように
color.mix()
で色を変換する - 1.で出力された
rgb()
形式のカラーをR/G/Bに分解する - 2.のカラーを16進に変換
- 3.を連結して
#rrggbb
を組み立てる
// sassモジュールの読み込み
@use 'sass:color';
@use 'sass:string';
@use 'sass:math';
// 関数の設定
// rgb()形式のカラー(0〜255)の数値を、2桁の16進文字列に変換
@function toHex($n) {
$hexchars: '0123456789abcdef';
$n: math.round($n);
$hi: math.floor(math.div($n, 16)) + 1;
$lo: ($n % 16) + 1;
@return string.slice($hexchars, $hi, $hi) + string.slice($hexchars, $lo, $lo);
}
// #rrggbbを返す関数
@function hexColor($c) {
$r: color.channel($c, 'red', $space: rgb);
$g: color.channel($c, 'green', $space: rgb);
$b: color.channel($c, 'blue', $space: rgb);
@return string.unquote('#' + toHex($r) + toHex($g) + toHex($b));
}
// colo.mix()の処理
@function colorMix($color, $weight) {
@return hexColor(color.mix($color, #fff, $weight * 1%));
}
// SCSSの表記
.example {
background: colorMix(#00619e, 30);
}
// コンパイルされたCSS(#00619eを30%まで薄くした色)
background: #b3d0e2;
この処理を挟むことで、color.mix()
の出力結果をrgb()
ではなくHEX形式にすることはできました。

出力されたカラーコードとしては、前回の記事の「mixを使用したSassの結果」と同じ結果となりました。
より正確に変換されていた結果を、曖昧な数値に戻してしまった、という感じですね。
なお、私は「色の濃度を変える」ことを目的としているので、color.mix()の2色目を#fff(白)に固定している+色の混ぜる割合($weight)の指定時の%表記をラクしてます。
本来は「2色を混ぜる」機能ですので、2色で行う場合はこちらで。
@function colorMix($color1, $color2, $weight: 50%) {
@return hexColor(color.mix($color1, $color2, $weight));
}
//SCSSの表記
.example {
background: colorMix(#ff0000, #00ffff, 20%);
}
まとめ
Dart Sass v3では、color.mix()
の結果がrgb()
で出力されてしまうため、HEX形式で出力するようにしてみた話でした。
前回の記事で、mixで出力した値が、ところどころ意図しない結果になっていたのが不思議でしたが、元々「内部的に計算した色」を無理やりHEX形式にしていたので誤差が出ていたのかなぁと、今さら気づきました。
今回も結果的には同じことをしているので、この小さな誤差を通していいのかはデザイナーさんにもご相談いただくなど、使用についてはご自身にて確認・判断いただければと思います。