近年のモダンなプロダクトやデザインシステムでは、プリミティブカラーとセマンティックカラーを分ける設計手法が標準となっています。この記事では、この2つの概念の違いから、最新のCSSカラープロパティ(OKLCH, color-mix)を駆使した、エンジニアリングとしての色彩設計を徹底解説します。
1. デザインを論理的に分解する「2つのレイヤー」#
CSSで管理する色には、大きく分けて2つの「階層」が存在します。
プリミティブカラー(素材の定義)#
色そのものの「パレット」を定義します。UI上の意味は持ちません。
:root {
--blue-500: #3b82f6;
--gray-200: #e5e7eb;
}セマンティックカラー(役割の定義)#
その色がUI上で果たす「意味」を定義します。
:root {
--color-brand: var(--blue-500);
--color-surface: var(--gray-200);
--color-text-main: #111827;
}なぜ分けるのか?: 「ブランドカラーを青から緑に変更する」際、プリミティブを参照しているセマンティックカラーを1行書き換えるだけで、サイト全体の整合性を保ったまま変更を完了できるからです。
2. 次世代の色彩管理:OKLCH 形式#
これまでエンジニアは HSL を愛用してきましたが、HSL には「色相によって人間の目に映る明るさが違って見える(黄色は明るく、青は暗く見える)」という弱点がありました。
OKLCH は、この問題を解決した「知覚的に均一な」カラースペースです。
.button {
/* L: 明度, C: 彩度, H: 色相 */
background: oklch(60% 0.15 250);
}OKLCH を使えば、「色相を変えても明るさが一定に保たれる」 ため、アクセシビリティ(コントラスト比)の管理が劇的に楽になります。
3. color-mix() による動的なカラー生成#
「メインカラーの 20% 透明バージョンが欲しい」といった場合、以前は新しい変数を定義する必要がありました。最新の CSS では color-mix() で解決できます。
.card {
/* ブランドカラーに白を20%混ぜる(=薄くする) */
background-color: color-mix(in oklab, var(--color-brand), white 20%);
/* ホバー時に少し暗くする */
&:hover {
background-color: color-mix(in oklab, var(--color-brand), black 10%);
}
}4. アクセシビリティ(WCAG)とコントラスト比#
エンジニアには、デザインが WCAG (Web Content Accessibility Guidelines) の基準を満たしているかを確認する「最後のフィルター」としての役割があります。
- AA基準 (4.5:1 以上): 通常のテキストに必須。
- AAA基準 (7:1 以上): より高いアクセシビリティが求められる場合。
ブラウザの DevTools を活用し、コントラスト比が足りない場合はデザイナーと相談するか、OKLCH の明度(L)を調整してロジカルに解決しましょう。
5. ダークモード設計の鉄則#
セマンティックカラーを採用していれば、ダークモードへの対応は変数の上書きだけで済みます。
:root {
--color-bg: oklch(98% 0 0);
--color-text: oklch(15% 0 0);
}
@media (prefers-color-scheme: dark) {
:root {
--color-bg: oklch(15% 0 0);
--color-text: oklch(95% 0 0);
}
}まとめ:色を「データ」として設計する#
CSSのカラー設計は、もはや「塗り絵」ではなく「データ構造の設計」です。
- プリミティブ(素材) と セマンティック(役割) を分ける。
- OKLCH で知覚的な整合性を保つ。
- color-mix() でバリエーションを動的に作る。
- アクセシビリティ を数値で担保する。
これらを意識するだけで、あなたの CSS は劇的に保守しやすく、ユーザーにとって優しいものになります。センスを磨く前に、まずは「論理」で色を管理することから始めてみてください。











