UIカラーにRGBではなくHSLを使うデベロッパーが増えている理由

RGBとHSLカラーモデルの比較 - コードエディタスタイルとカラースウォッチ付き

HSLカラーモデル (色相・彩度・輝度) は、CSS で色を扱う際に RGB よりもはるかに直感的な方法を開発者に提供します。赤・緑・青の値をどう組み合わせれば目的の色になるかを試行錯誤する必要はありません。HSL では、脳が色を認識する方法そのままに色を記述できます。まず色を選び、次にその鮮やかさを決め、最後に明るさを調整するだけです。この考え方の違いこそが、多くの開発者が rgb() から hsl() へ移行している理由です。

RGB と HSL - 基本的な違い

RGB は赤・緑・青の3つの光チャンネルをそれぞれ 0 から 255 の値で混合することで色を定義します。しかし、これはスクリーンがピクセルをレンダリングする仕組みであり、人間が色を知覚する方法とは異なります。RGB で少し明るい青を作りたい場合、3つのチャンネルすべてを適切な比率で調整しなければなりません。調整のための単一のパラメータが存在しないのです。

HSL は、人が日常的に色を表現する方法に直接対応しています。

  • 色相 (Hue) - 実際の色を表し、360度のカラーホイール上の角度で指定します。赤が 0、緑が 120、青が 240 です。
  • 彩度 (Saturation) - 色の鮮やかさを表し、0% (純粋なグレー) から 100% (最大限に鮮やか) の範囲で指定します。
  • 輝度 (Lightness) - 色の明暗を表し、0% (黒) から 100% (白) の範囲で指定します。50% が「純粋な」色になります。

同じ中間色の青を両方の形式で表すと次のようになります。

/* RGB - what do these numbers even mean at a glance? */
color: rgb(70, 130, 180);

/* HSL - instantly readable: blue hue, moderate saturation, medium lightness */
color: hsl(207, 44%, 49%);

どちらもスチールブルーを表しています。しかし、一目で意味がわかるのは HSL の方だけです。色相が 207 (青系)、彩度は中程度の 44%、輝度はほぼ中央の 49% です。カラーピッカーを開かなくても頭の中で色をイメージできます。

特性 RGB HSL
人間が読みやすいか ほとんどない はい
色を明るく・暗くする 3つの値を調整 輝度のみ調整
彩度を変更する 3つすべてを再計算 彩度のみ調整
カラーパレットを作成する 試行錯誤が必要 色相を度数で回転させるだけ
CSS 変数でのテーマ設定 冗長になりやすい シンプルで予測しやすい

CSS における HSL の構文

CSS の hsl() 関数は CSS3 からサポートされています。モダンな構文 (CSS Color Level 4) では、 hsl() の中に直接アルファ値の第4パラメータを指定できるため、 hsla() はほぼ不要になっています。

/* Classic syntax */
color: hsl(207, 44%, 49%);

/* With alpha (transparency) - old way */
color: hsla(207, 44%, 49%, 0.8);

/* Modern CSS Color Level 4 syntax - commas optional, alpha with slash */
color: hsl(207 44% 49%);
color: hsl(207 44% 49% / 0.8);
color: hsl(207 44% 49% / 80%);

主要なブラウザはどちらの構文もサポートしています。カンマなしの構文が CSS の今後の方向性ですが、カンマあり構文は Internet Explorer 9 以降を含むすべての環境で動作します。

UI 開発で HSL が優れている理由

HSL の真価は、色のバリエーションを生成する必要があるときに発揮されます。これは UI 開発では日常的に起こることです。

カラーパレットをすばやく構築する

たとえば、ブランドカラーが hsl(140, 70%, 45%) の鮮やかな緑だとします。ホバー状態・無効状態・薄い背景色のティントが必要な場合、HSL ならそれぞれ1つの値を変えるだけで済みます。

--color-base:     hsl(140, 70%, 45%);  /* base green */
--color-hover:    hsl(140, 70%, 38%);  /* darker - just lower lightness */
--color-disabled: hsl(140, 20%, 65%);  /* washed out - lower saturation */
--color-tint:     hsl(140, 70%, 92%);  /* very light background tint */

カラーピッカーなしで RGB を使って同じことを予測可能な形で行うのは、本当に難しいです。調整できる独立した軸が存在しないからです。

類似色と補色

色相はカラーホイール上の角度なので、調和のとれたパレットの生成は単純な算術で実現できます。類似色は互いに 30 度以内、補色は 180 度離れています。

--primary:       hsl(210, 80%, 50%);   /* blue */
--analogous-1:   hsl(180, 80%, 50%);   /* cyan - 30 degrees left */
--analogous-2:   hsl(240, 80%, 50%);   /* purple - 30 degrees right */
--complementary: hsl(30, 80%, 50%);    /* orange - 180 degrees opposite */

彩度と輝度は同じままなので、色のまとまりが生まれます。これはまさに Tailwind CSS や Material Design といったデザインシステムがカラースケールをプログラムで生成する方法です。

CSS の実践的な使用例

HSL の各値を CSS カスタムプロパティで管理する

HSL の強力なパターンの一つは、3つの値をそれぞれ別の CSS カスタムプロパティに分割することです。これにより、どこでも自由に組み合わせて使え、個々のチャンネルをその場で調整できます。

:root {
  --brand-h: 210;
  --brand-s: 80%;
  --brand-l: 50%;
  --brand-color: hsl(var(--brand-h), var(--brand-s), var(--brand-l));
}

.button {
  background-color: var(--brand-color);
}

.button:hover {
  /* Just override lightness - no need to redefine the whole color */
  background-color: hsl(var(--brand-h), var(--brand-s), 40%);
}

.button:disabled {
  background-color: hsl(var(--brand-h), 20%, 70%);
}
構文に関する注意: hsl() の中で CSS カスタムプロパティを使用する場合は、カンマが必要です: hsl(var(--h), var(--s), var(--l)) 。カンマなしのモダン構文は、すべてのブラウザで var() hsl() の中で使う際にまだ対応していません。

完全なトーンスケールを生成する

デザインシステムでは、単一の色について 9-10 段階のシェードが必要になることがよくあります (Tailwind の 50 から 950 のスケールなど)。HSL では、色相と彩度を固定したまま輝度を一定間隔でステップさせることで、スケール全体を生成できます。

:root {
  --blue-50:  hsl(210, 80%, 95%);
  --blue-100: hsl(210, 80%, 87%);
  --blue-200: hsl(210, 80%, 76%);
  --blue-300: hsl(210, 80%, 65%);
  --blue-400: hsl(210, 80%, 55%);
  --blue-500: hsl(210, 80%, 50%);  /* base */
  --blue-600: hsl(210, 80%, 43%);
  --blue-700: hsl(210, 80%, 36%);
  --blue-800: hsl(210, 80%, 26%);
  --blue-900: hsl(210, 80%, 16%);
}

CSS のカラーフォーマット同士の関係についてより詳しく知りたい方は、 HEX から RGB への変換ガイド で、各フォーマットをいつ使うべきかを含めた CSS カラーフォーマットの全体像を確認できます。

ホバー状態・テーマ設定・ダークモード

ホバー状態とフォーカス状態

HSL を使うと、ホバー状態の定義が簡単になります。まったく別の色を定義する必要はなく、輝度を少し変えるだけです。

.btn-primary {
  background: hsl(210, 80%, 50%);
  transition: background 0.2s ease;
}

.btn-primary:hover  { background: hsl(210, 80%, 43%); }
.btn-primary:active { background: hsl(210, 80%, 36%); }
.btn-primary:focus-visible {
  outline: 3px solid hsl(210, 80%, 70%);
}

各状態がベースカラーとどう関係しているかが一目瞭然です。このコードを読んだチームメンバーも、状態間の関係をすぐに理解できます。

HSL 変数を使ったテーマ設定

HSL はモダンな CSS テーマ設定の基盤です。色相だけを変数として公開することで、ユーザーや管理者が1つの数値を変えるだけでアプリ全体のカラースキームを変更できるようになります。

/* Default theme: blue */
:root {
  --theme-hue: 210;
}

/* Green theme - just swap the hue */
[data-theme="green"] {
  --theme-hue: 140;
}

/* Purple theme */
[data-theme="purple"] {
  --theme-hue: 270;
}

/* All components use the same hue variable */
.button      { background: hsl(var(--theme-hue), 75%, 50%); }
.link        { color: hsl(var(--theme-hue), 75%, 40%); }
.badge       { background: hsl(var(--theme-hue), 75%, 92%); color: hsl(var(--theme-hue), 75%, 25%); }
.focus-ring  { outline-color: hsl(var(--theme-hue), 75%, 65%); }

HSL を使ったダークモード

ダークモードの実装こそ、HSL が最も力を発揮する場面です。2つの完全に別個のカラーパレットを管理する代わりに、同じ色相のまま輝度の値を反転させるだけで済みます。

:root {
  --bg:   hsl(210, 20%, 98%);   /* near-white background */
  --text: hsl(210, 20%, 15%);   /* near-black text */
  --card: hsl(210, 20%, 93%);   /* slightly darker card */
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:   hsl(210, 20%, 10%);  /* flip: near-black background */
    --text: hsl(210, 20%, 90%);  /* flip: near-white text */
    --card: hsl(210, 20%, 15%);  /* slightly lighter card in dark */
  }
}

色相 (210) と彩度 (20%) はまったく変わっていません。変化するのは輝度だけです。これにより、ダークモードでも同じデザインを保ちながら明暗を反転させるという、理想的なダークモードの実装が実現できます。

ブラウザサポートと互換性

HSL のブラウザサポートは非常に充実しています。 hsl() 関数は以下のバージョンから利用可能です。

  • Chrome 1 (2008年)
  • Firefox 1 (2004年)
  • Safari 3.1 (2008年)
  • Internet Explorer 9 (2011年)
  • Edge 12 (2015年)

カンマなしのモダン構文 ( hsl(210 80% 50%) ) とスラッシュによるアルファ構文 ( hsl(210 80% 50% / 0.5) ) は CSS Color Level 4 仕様 の一部であり、2023年時点ですべてのモダンブラウザでサポートされています。IE11 のサポートが必要な場合 (現時点では稀なケースですが) は、カンマ構文を使用してください。

今すぐ安心して使えます: カンマありの hsl() は、ユーザーが使用している可能性のあるすべてのブラウザで動作します。スペース区切りのモダン構文は Chrome 90 以降・Firefox 89 以降・Safari 14.1 以降でサポートされており、グローバルブラウザ使用率の 95% 以上をカバーしています。

HSL・RGB・HEX の各フォーマット間で値を相互変換したい場合や、特定のフォーマットしか受け付けないツールに色を渡す必要がある場合は、 カラーピッカー を活用してください。

HSL vs OKLCH - 次の選択肢は?

HSL をさらに深く掘り下げたい場合は、 OKLCH を知っておく価値があります。OKLCH は知覚的に均一な色空間であり、輝度やクロマの数値を等間隔で変化させると、人間の目にも等間隔の変化として見えます。HSL ではこれが完全には保証されません。

HSL の問題点は、同じ輝度の値を持つ2色でも、知覚される明るさが大きく異なる場合があることです。たとえば、 hsl(60, 100%, 50%) (黄色) は hsl(240, 100%, 50%) (青) よりもはるかに明るく見えますが、どちらも輝度は 50% です。OKLCH はこの問題を補正します。

/* HSL - same lightness, different perceived brightness */
color: hsl(60, 100%, 50%);   /* yellow - looks very bright */
color: hsl(240, 100%, 50%);  /* blue - looks much darker */

/* OKLCH - same lightness, actually looks the same to the eye */
color: oklch(0.75 0.18 90);   /* yellow-ish */
color: oklch(0.75 0.18 260);  /* blue-ish - genuinely similar perceived brightness */

OKLCH は HSL が対応している sRGB の範囲を超えた 広色域カラー (P3 ディスプレイカラー) もサポートしています。 oklch() のブラウザサポートは 2024 年時点で十分な水準に達しており、Chrome 111 以降・Firefox 113 以降・Safari 15.4 以降で利用できます。

現時点でほとんどのプロジェクトにとって、HSL は実用的なベストバランスの選択肢です。可読性が高く、保守しやすく、あらゆるブラウザでサポートされており、RGB と比べて大幅な改善をもたらします。OKLCH が適しているのは、数学的に一貫したコントラスト比が必要なデザインシステムを構築する場合や、広色域ディスプレイをターゲットにする場合です。

カラーパレットを構築しながら色の関係を視覚的に確認したい場合は、 カラーエクスプローラーツール を使うと、色相の回転・彩度の変化・輝度の変化がリアルタイムでどのように相互作用するかを実際に試せます。

色相・彩度・輝度のスライダーを表示した HSL カラーピッカーツール

HSL カラーを直感的に選ぼう

カラーピッカーを使えば、色相・彩度・輝度の値をビジュアルで調整し、HSL カラーモデルの出力をそのまま CSS にコピーできます。計算は不要です。

カラーピッカーを試す →

全面的な書き直しは必要ありません。ただし、新しく色を定義する際は HSL に切り替える価値があります。特に CSS カスタムプロパティを使う場合はなおさらです。最も恩恵を受けられるのは、デザインシステムの構築・保守、ホバー状態の実装、ダークモードの実装などの場面です。同じプロジェクト内で RGB と HSL を混在させることは完全に有効な CSS であり、ブラウザはパフォーマンスの差なく両方を処理します。

いいえ、意味のあるパフォーマンスの差はありません。ブラウザはすべての CSS カラーフォーマットをパース時に内部表現に変換するため、 hsl(207, 44%, 49%) と書いても rgb(70, 130, 180) と書いても、その後のレンダリングエンジンの処理は同じです。選択はあくまで開発者体験と保守性の問題であり、ランタイムのパフォーマンスとは無関係です。

はい、これは HSL の JavaScript における最も強力なユースケースの一つです。色相・彩度・輝度をそれぞれ別の数値として保持し、カラー文字列を動的に構築できます: element.style.color = `hsl(${hue}, ${saturation}%, ${lightness}%)` 。アニメーション・テーマの切り替え・インタラクティブなカラーコントロールの実装が、RGB チャンネルを使う場合よりもはるかにシンプルになります。RGB で同じ効果を得るには変換の計算が必要になります。

HSL (色相・彩度・輝度) と HSB/HSV (色相・彩度・明度) は、色相の軸を共有していますが、異なるカラーモデルです。HSL では輝度 50% が純粋な完全彩度の色になります。HSB では明度 100% が純粋な色になります。同じ彩度と明度/輝度の値でも、2つのモデルは異なる結果を生成します。CSS では HSL を使用します。HSB/HSV は Photoshop や Figma などのデザインツールで一般的ですが、CSS のネイティブフォーマットではありません。

HEX から HSL への変換は、中間ステップとして RGB を経由します。まず HEX のペアを RGB 値 (0-255) に変換し、0-1 に正規化してから HSL の変換式を適用します。実際には、ほとんどの開発者はカラーピッカーツール・Figma などのデザインツール・ブラウザのデベロッパーツールのカラーピッカーを使って即座に変換します。ブラウザのデベロッパーツールでは、カラースウォッチをクリックするだけで HEX・RGB・HSL の表示を切り替えられます。

はい、OKLCH はアクセシビリティ対応においてより信頼性が高いです。知覚的に均一な色空間であるため、輝度チャンネルの等間隔の変化が、知覚される明るさの等間隔の変化に対応します。これにより、異なる色相間でもコントラスト比が予測しやすいカラーパレットを構築しやすくなります。HSL では、輝度 50% の黄色が同じく輝度 50% の青よりもはるかに明るく見えるため、アクセシビリティ上の予期しない問題が生じることがあります。WCAG のコントラスト準拠を目指す場合、アクセシブルなカラースケールを構築する際に OKLCH の方がより予測可能な結果をもたらします。