color-mix() の色空間による違い
検証
色を混合する CSS の color-mix()
は、使い勝手の良い関数です。
第 1 引数には色空間を指定します。その色空間の違いにより、どれほど色が変わるのかを確認したくなり一覧を作りました。対象は 15 の色空間です。ただ、<hue-interpolation-method>
は無視しています。初期値の色は、赤の #ff0000
と青の #0000ff
です。
- srgb
- srgb-linear
- display-p3
- a98-rgb
- prophoto-rgb
- rec2020
- lab
- oklab
- xyz
- xyz-d50
- xyz-d65
- hsl
- hwb
- lch
- oklch
どの色空間を使うか
color-mix()
は 15 の色空間を使えますが、ほとんどのサイトでは srgb
を使うことになると思います。
より鮮やかな色を表現できる display-p3
を使いたいと私はよく思うのですが、Android 版と Windows 版のブラウザが Display P3 に対応していません。Chrome は実験フラグの chrome://flags/#force-color-profile
でカラープロファイルを変更し Display P3 D65 に対応できますが、ディスプレイ側が対応していなければ色が正確に表示されません。
場合によっては color-gamut
を使い、DCI-P3 に対応していれば display-p3
、対応していなければ srgb
を使うケースがあるかもしれません。
@media (color-gamut: p3) {
:root {
--color-space: display-p3;
}
}
p {
background-color: color-mix(in var(--color-space, srgb), #f00, #00f);
}
ただ、@media (color-gamut: p3)
は、ユーザーエージェントおよび出力機器が DCI P3 に「ほぼ」対応しているかを調べます。DCI P3 75% のディスプレイと実験フラグで Display P3 D65 を選択した Windows 版 Chrome で調べたところ、DCI P3 にほぼ対応していると判定しました。DCI P3 75% のディスプレイでは正確に表現できない Display P3 の色が出てくるため、不都合が生じるかもしれません。
また、color()
も任意の色空間を指定できる CSS の関数です。color-mix()
で display-p3
など特定の色空間を使用したい場合は、同じ色空間を指定した color()
を使い色を指定すればサイト全体の色に統一感が出るかもしれません。
color-mix()
や色空間の詳しい説明は、以下のページなどをご参考ください。
高頻度の使用ケース
最後に、私が color-mix()
を頻繁に使用する 2 つのケースを書きます。
1 つ目が、HEX に透明度を加える時です。これは color-mix()
の便利な使い方としてよく紹介されています。
color-mix(in srgb, #f00 40%, transparent)
color-mix()
で作った色に color-mix()
で透明度を加えることもあります。
color-mix(in srgb, color-mix(in srgb, #f00, #00f) 40%, transparent)
2 つ目が、マテリアルデザイン 3 の インタラクションの状態 です。State layers にて説明がありますが、ホバーやフォーカスなどの時に背景色の上に半透明の文字色のレイヤーで覆い状態の変化を視覚的に示します。以前までは HTML を工夫するか、CSS の ::before
や ::after
疑似要素を使うか、Colord のような npm パッケージを使ってあらかじめ色を作っておくかして実装していました。今は background-color
に color-mix()
を使っています。例えば、このような <button>
があるとします。
<button class="states" data-color-role="primary" type="button">ボタン</button>
そして、background-color
に color-mix()
を使います。フォーカス時に 10%、ホバー時に 8% の量の文字色を背景色に混ぜます。また、ライトモードとダークモードに対応するために、color-mix()
には light-dark()
を使い色を指定します。
:root {
color-scheme: light dark;
}
/* ライトモードの背景色は#65558f、文字色は#ffffffとする */
/* ダークモードの背景色は#d0bcfe、文字色は#381e72とする */
[data-color-role='primary'] {
--bg-color: light-dark(#65558f, #d0bcfe);
--text-color: light-dark(#fff, #381e72);
}
.states {
background-color: color-mix(
in srgb,
var(--bg-color),
var(--text-color) var(--state-opacity, 0%)
);
color: var(--text-color);
/* フォーカス時に10%の量の文字色を背景色に混ぜる */
&:focus-visible {
--state-opacity: 10%;
}
/* ホバー時に8%の量の文字色を背景色に混ぜる */
@media (any-hover: hover) {
&:hover {
--state-opacity: 8%;
}
}
}