テック技報最新号へ →
CSS

color-mix() で1つのブランド色からホバー用の濃い色・薄い背景色を作る

color-mix(in oklch, var(--brand), black 20%) で濃い色、transparent と混ぜて薄い色を作れば、--brand を1か所変えるだけで派生色がすべて追従する。

@gkurttech · 投稿 2026-11-07

どんな時に使う?

ボタンのホバー色、押下時の色、選択中の行の薄い背景など、ブランド色の「濃い版・薄い版」を何色も用意しているとき。hex を1色ずつベタ書きすると、テーマ色を変えた時に派生色だけ古いまま残りがち。color-mix() で元の色から計算しておけば、トークンが1つで済む。

コード

css
:root {
  --brand: oklch(0.62 0.19 255);

  /* 黒を 20% 混ぜて濃く(ホバー) */
  --brand-hover: color-mix(in oklch, var(--brand), black 20%);
  /* 黒を 35% で、さらに濃く(押下) */
  --brand-active: color-mix(in oklch, var(--brand), black 35%);
  /* 白を混ぜて明るく(不透明なまま淡い色) */
  --brand-light: color-mix(in oklch, var(--brand), white 80%);
  /* 透明と混ぜて薄く(下地が透ける淡い背景) */
  --brand-soft: color-mix(in oklch, var(--brand) 18%, transparent);
}

.button { background: var(--brand); }
.button:hover { background: var(--brand-hover); }
.button:active { background: var(--brand-active); }
.row[aria-selected="true"] { background: var(--brand-soft); }
  • 書き方は color-mix(in <色空間>, 色A 割合, 色B 割合)。割合を片方だけ書くと、もう片方は残り(100% − 指定)になる。var(--brand), black 20% は「ブランド 80% + 黒 20%」。
  • 色空間は in oklch か in oklab にすると、sRGB で混ぜた時より濁りにくく、明るさの変化も均一に感じやすい(混ぜ方の違いは グラデーションに in oklch を付けて、色の途中が灰色に濁らないようにする と同じ考え方)。
  • white を混ぜた淡い色は不透明、transparent を混ぜた淡い色は半透明。背景の上に重ねる場所では前者、下地を透かしたい場所では後者を使い分ける。

注意点・対応状況

  • color-mix() は Chrome / Edge 111+、Safari 16.2+、Firefox 113+ で、Baseline Widely available。
  • 透明度だけ変えたい場合は、より短く書ける alpha() もある(alpha() でカラートークンの薄い背景色を作る)。ただし alpha() は 2026-09 に揃ったばかりなので、古い環境では color-mix(..., transparent) が保険になる。
  • 黒を混ぜた濃い色は、元の色によっては彩度が落ちてくすむ。気になる時は相対カラー構文で明るさだけ下げる(例: oklch(from var(--brand) calc(l - 0.1) c h))方法もある。
  • ダークテーマでは「ホバーで濃く」が逆に見えにくくなることがある。テーマごとに black / white を入れ替えるか、light-dark() と組み合わせて調整する。
  • 文字色とのコントラストは、混ぜた後の実際の色で確認すること。

出典

X の元の投稿を開く