CSS color-mix() と OKLCH — ブランドカラーから自動でホバー/無効色を導く設計
GDESIGN
デザイン(更新: 2026-09-06)7 分で読める

CSS color-mix() と OKLCH — ブランドカラーから自動でホバー/無効色を導く設計

ブランドカラーからホバー色、背景、境界線を組み立てるとき、CSSの color-mix() とOKLCHは派生色の定義をまとめる手段になります。ただし、色を計算できることと、コントラストや状態の分かりやすさを満たすことは別です。本記事では2色の混色とCSS変数を使い、検証を伴う設計パターンを整理します。

#CSS#color-mix#OKLCH#デザインシステム#色空間

sRGB・HSL・OKLCHは何を表すか

sRGBはWebで広く使われるRGB色空間です。HSLはRGBを色相・彩度・明度として操作する表現ですが、HSLの同じLが知覚上の同じ明るさを意味するわけではありません。

たとえば hsl(60 100% 50%)hsl(240 100% 50%) は同じLでも、相対輝度が大きく違います。HSLのLはRGB成分の最大値と最小値から求める値で、視覚に合わせた明度尺度ではないためです。

CIELABやOklabは知覚的な差をより扱いやすくする色空間です。OklabはBjörn Ottossonが2020年に公開したもので、OKLCHはその極座標表現です。知覚的な均等性は近似であり、すべての色・環境で完全な一致を保証しません。

OKLCHのL・C・H

OKLab は 2020 年に Björn Ottosson が発表した "A perceptual color space for image processing" で提案された色空間です。青色域を含む知覚上の扱いやすさを改善することを目指しています。P3等の色域を扱えますが、任意のOKLCH値をすべての画面がそのまま表示できるわけではありません。

OKLCH は OKLab の極座標表現 (円筒座標):

  • L (Lightness): 0〜1、知覚上の明度
  • C (Chroma): クロマ。0は無彩色で、0.4は仕様上の上限ではない。表示可能な範囲はL・Hと対象色域によって変わる
  • H (Hue): 0〜360 度、色相
/* CSS 構文 */
oklch(62.3% 0.214 259.815)   /* Tailwind v4 の blue-500 公式値 */
oklch(0.623 0.214 259.815)   /* 小数表記 */

HSL と違い、同じ L 値なら違う色相でも知覚明度がほぼ等しくなるのが最大の利点。デザインシステムで「この色と同じ明るさの別の色が欲しい」というニーズに応えられます。

ここでのLはWCAGの相対輝度ではありません。同じLをそろえても、背景とのコントラスト適合は別途計算します。

color-mix()の構文と補間経路

この記事で使うのは、色空間と2色を指定する構文です。省略した比率の扱い、合計が100%でない場合の正規化、アルファも結果に影響します。

color-mix(in srgb, red 50%, blue)
color-mix(in oklch, #2563eb 80%, white)
color-mix(in oklch, #2563eb, black 30%)
color-mix(in oklch longer hue, red, blue)

最初の例は50:50、2番目は80:20、3番目は70:30です。色相を持つ空間では shorter huelonger hue が経路を変えます。OKLCHなら常に期待どおりの色になる、灰色を避けられる、という保証はありません。

透明色との混色ではアルファが変わり、見える色は背景との合成で決まります。色域外の値は出力時の色域マッピング等も影響するため、実際の画面で確認します。

ブランドカラーから派生色を自動生成するパターン

単一ブランドカラー --brand: #2563eb から、以下を自動生成できます。

:root {
  --brand: #2563eb;

  /* インタラクション状態 */
  --brand-hover:    color-mix(in oklch, var(--brand), white 15%);
  --brand-active:   color-mix(in oklch, var(--brand), black 15%);
  --brand-disabled: color-mix(in oklch, var(--brand), transparent 60%);

  /* ボーダー用の薄い色 */
  --brand-border:   color-mix(in oklch, var(--brand), white 70%);

  /* 背景用の超薄い色 (カード背景等) */
  --brand-bg:       color-mix(in oklch, var(--brand), white 92%);

  /* フォーカスリング */
  --brand-focus:    color-mix(in oklch, var(--brand), transparent 70%);
}

.button {
  background: var(--brand);
  border: 1px solid var(--brand-border);
}
.button:hover { background: var(--brand-hover); }
.button:active { background: var(--brand-active); }
.button:disabled { background: var(--brand-disabled); }

この仕組みなら、ブランドカラーを赤に変えるだけで、すべての派生色が追従します。デザイントークンを変えるコストが劇的に下がります。

これは色を生成する例で、検証済みの完成パレットではありません。白文字を載せるホバー色、半透明のフォーカス表示、境界線は実背景と組み合わせて確認してください。無効コントロールにはWCAGの適用例外がありますが、状態が分かる設計は必要です。

ライトモード・ダークモードの自動化

ダークモード対応も color-mix() で大幅に簡潔化できます。

:root {
  --text: #1f2937;
  --bg:   #ffffff;
  --accent: #2563eb;
}

[data-theme="dark"] {
  --text: #e5e7eb;
  --bg:   #111827;
  /* アクセント色は明度を反転気味に */
  --accent: color-mix(in oklch, #60a5fa, transparent 0%);
}

/* 共通: 派生色は color-mix で自動追従 */
.card {
  background: color-mix(in oklch, var(--bg), var(--accent) 5%);
  border-color: color-mix(in oklch, var(--text), transparent 85%);
}

従来は「ライト用」「ダーク用」の色を全ペアで定義していましたが、基本色 3〜5 個を ライト/ダークで指定すれば、派生色の式を共有できるのが特徴です。

transparent 0%の例は元の色を維持するもので、明度を反転する演算ではありません。ダーク用アクセントを別に選び、すべての派生色と背景の組合せを確認します。

対応機能を確認し、フォールバックを分ける

2026年9月5日に確認したMDNの互換データでは、基本の oklch() はChrome/Edge 111、Firefox 113、Safari 15.4から、2色の color-mix() はChrome/Edge 111、Firefox 113、Safari 16.2から対応しています。相対色構文や新しい拡張構文の対応は別に確認します。ここから市場全体の対応率は推定しません。

カスタムプロパティは未対応関数を含む文字列も保持できるため、同じ変数を前後に書くだけでは古い値に戻らない場合があります。機能検出の内側で変数を更新します。

:root { --brand-hover: #3b7ced; }
@supports (color: color-mix(in oklch, red, blue)) {
  :root { --brand-hover: color-mix(in oklch, #2563eb, white 15%); }
}
.button:hover { background-color: var(--brand-hover); }

静的な値は代替色で、混色結果と完全一致する保証ではありません。旧環境では代替色、新環境では計算色を、それぞれ背景・文字色と確認します。機能検出の成功も、ブラウザ固有の表示差がないことの保証にはなりません。

Tailwind CSSでの色定義

Tailwind CSS v4の公式カラー定義はOKLCHを使います。たとえば --color-blue-500: oklch(62.3% 0.214 259.815) です。v3の標準パレットを一律にHSLベースだったとは説明しません。

組み込みの色を使う場合も、背景・文字・状態の組合せで検証します。OKLCHの採用だけで広色域表示やアクセシビリティが自動的に保証されるわけではありません。

色彩設計のベストプラクティス

  1. ブランドカラーは OKLCH で定義 (あるいは HEX から変換ツールで算出)
  2. 派生色は color-mix(in oklch, ...) で数式生成
  3. 同じ L 値をキープしてシリーズを作る (知覚明度が揃う)
  4. アクセシビリティ: 通常文字のAAでは、適用例外を除いてWCAGコントラスト比4.5:1以上を WCAG チェッカー で検証
  5. ライト/ダークは基本色のみ切替、派生色は color-mix で自動追従
  6. 旧ブラウザ向けには静的値を定義し、@supports内で計算値へ更新
  7. デザイントークンは CSS Variables + セマンティック命名 (--color-primary よりも --brand-hover, --text-muted 等)

まとめ

  • OKLCHは知覚的な明度・クロマ・色相で色を扱うための表現。
  • color-mix()は派生色の式を共有する手段で、コントラストの合格保証ではない。
  • 比率、色相経路、透明度、背景、色域を分けて確認する。
  • 未対応環境への変数フォールバックは@supportsで分離する。
  • 基本構文と拡張構文の対応を混同せず、ライト・ダーク両方で評価する。

参考文献・ソース

記事作成に関する注記

本記事は AI(大規模言語モデル)を編集補助として活用して作成しています。 公開前に編集者が内容を確認していますが、事実誤認・仕様の解釈ミス・最新情報との齟齬が含まれる可能性があります。 重要な判断を行う際は、本文中の一次ソースや公式ドキュメントを必ずご自身でご確認ください。 誤りにお気づきの場合は、お問い合わせフォームよりご連絡いただけると助かります。

🔧 関連ツール

📚 関連記事