CSS変数とHSLで一貫したテーマカラー設計
ブランドカラーを :root に直接書くだけだと、ホバー色・ダークモード・将来のリブランドが破綻しがちです。HSLを色相(H)/彩度(S)/明度(L)の3つに分けてCSS変数化することで、ホバー時に「明度だけ-10%」のような差分の効く設計が可能になります。
1. なぜHSLを分解するのか
background-color: #2563eb; をホバー時に少し暗くしたい場合、HEXのままでは「暗い版」のHEXを別途用意するしかありません。一方HSL(hsl(221, 83%, 53%))なら、彩度Sと色相Hを固定したまま明度Lを43%や63%にするだけで「同系色の明るさ違い」が作れます。これをCSS変数に分けて --brand-h: 221; --brand-s: 83%; --brand-l: 53%; と書いておくと、hsl(var(--brand-h) var(--brand-s) var(--brand-l)) で通常時、hsl(var(--brand-h) var(--brand-s) calc(var(--brand-l) - 10%)) でホバー時という設計ができます。
2. ダークモードの最小切替
ダークモードはCSSの @media (prefers-color-scheme: dark) で発動します。HSLの明度Lだけ反転(53%→47%や、52%→90%)すれば、色相と彩度はそのままに「同じブランド色のダーク版」が作れます。コードは :root { --brand-l: 53%; } @media (prefers-color-scheme: dark) { :root { --brand-l: 70%; } } のように1行で完結。全色一括の色変更が、設計次第で5〜10行の差分に収まります。
3. ブランドスケールを増やす設計
Tailwind CSSのようなブランドカラーの50/100/200…900のスケールを自前で組むなら、HSLの明度Lを {50: 97%, 100: 93%, 200: 87%, 300: 78%, 400: 66%, 500: 53%, 600: 43%, 700: 35%, 800: 28%, 900: 22%} のように設計します。色相Hと彩度Sは固定で、明度Lのみを動かす設計だと、見た目に統一感のあるカラースケールができます。
4. 補色・アクセントカラーをHから派生
HSLの色相Hは0〜360度の色相環で、補色は180度反対側です。ブランドカラーが青(H=221)なら、補色はオレンジ系(H=41)です。アクセントカラーが必要なときは、Hを「+30度(青→紫)」「+60度(青→マゼンタ)」「+180度(青→オレンジ)」と動かすと、彩度・明度を保ったまま「ブランドと調和する別色」を得られます。CSSではhsl(calc(var(--brand-h) + 180deg) var(--brand-s) var(--brand-l))で書けます。
5. oklch()との比較
CSS Color Module Level 4ではoklch()という新しい関数も使えます。HSLは数式上の単純な変換ですが、人間の目には色相を動かしたとき明るさが揃って見えない場合があります。oklch()は知覚均等を考慮した設計で、青と黄を同じ明度で並べてもムラなく見えます。ただしブラウザ対応は2023年以降で歴史が浅く、IE系の代替指定も難しいので、まずはHSLで設計してから、必要に応じてoklch()に移行する流れが現実的です。
6. デザイナーへの説明
HSLでテーマ設計するメリットをデザイナーに説明するなら、「ホバー色・ダーク色・無効状態色は全て『明度の差分』で作っています」と一言伝えれば伝わります。実装側で色をオリジナルから派生させる仕組みがあると、デザイナーがブランドカラーを微調整したい時、HEX 1つ変えるだけでサイト全体の派生色が連動するのが大きな利点です。カラーコード変換ツールでHEXからHSLへの変換を頻繁に行うとこの設計に慣れます。