OKLCHとHSLの違い - 同じ明度50%なのに明るさが違う問題を解決する
HSL で hsl(60 100% 50%)(黄)と hsl(240 100% 50%)(青)を並べると、同じ「明度 50%」のはずなのに黄色のほうが圧倒的に明るく見えます。 これは HSL が人間の知覚ではなく sRGB の数値構造から機械的に計算された色空間だからです。 CSS Color Module Level 4 で導入された oklch() は、この問題を解決する 知覚均等(perceptually uniform)な色空間です。本記事では HSL の何が問題か、OKLCH の構文、 ブラウザ対応、color-mix() との組み合わせ、デザインシステムでの実践までを整理します。
HSL lightness is computed from sRGB geometry, so two colors with the same L can differ wildly in perceived brightness. OKLCH, added in CSS Color Level 4, fixes this with a perceptually uniform lightness axis. This guide covers the syntax, browser support, and how to use it with color-mix().
TL;DR
- HSL の L は計算上の値。色相が違うと同じ L でも見た目の明るさが全く違う(黄と青で相対輝度は約13倍差)
- OKLCH の L は知覚的明度。L が同じなら色相を変えてもほぼ同じ明るさに見える
- 構文は
oklch(L C H / alpha)。例:oklch(0.7 0.15 230) - 2026年時点で
oklch()・color-mix(in oklch, ...)・相対カラー構文は全モダンブラウザ対応 - C(彩度)は sRGB では概ね 0〜0.37。ガモット外はブラウザが自動マッピング
- Tailwind CSS v4 はデフォルトパレットを OKLCH で定義。新規のパレット設計は OKLCH が第一候補
1. HSL の何が問題か / The problem with HSL
HSL は色相(Hue)・彩度(Saturation)・明度(Lightness)という直感的な軸を持ちますが、 値は sRGB の RGB 値から幾何的に導出されたもので、人間の目の感度は一切考慮されていません。 純色(S=100%, L=50%)を並べると差は歴然です。
| 色 / Color | HSL | 相対輝度 / Luminance | OKLCH の L |
|---|---|---|---|
黄 #ffff00 | hsl(60 100% 50%) | 0.928 | 0.968 |
緑 #00ff00 | hsl(120 100% 50%) | 0.715 | 0.866 |
赤 #ff0000 | hsl(0 100% 50%) | 0.213 | 0.628 |
青 #0000ff | hsl(240 100% 50%) | 0.072 | 0.452 |
4色とも HSL では「明度 50%」ですが、相対輝度は 0.072〜0.928 と約13倍の開きがあります。 一方 OKLCH の L はこの見た目の差を素直に反映しています(黄 0.968、青 0.452)。 この性質のため、HSL で「L を固定して H だけ回す」方法でカテゴリカラーやバッジ色を量産すると、 明るさがバラバラでコントラスト比も不揃いなパレットになります。
All four colors above share L=50% in HSL, yet their relative luminance spans a 13x range. OKLCH lightness tracks what you actually see, which is why hue-rotation tricks break in HSL.
2. OKLCH とは - oklch() の構文と読み方 / What OKLCH is
OKLCH は、Björn Ottosson 氏が 2020 年に発表した Oklab 色空間を 明度 L・彩度 C・色相 H の極座標で表したものです。CSS Color Module Level 4 にoklch() 関数として採用されています。
/* oklch(明度 彩度 色相 / 不透明度) */
color: oklch(0.7 0.15 230); /* 落ち着いた青 */
color: oklch(70% 0.15 230); /* L はパーセント表記でも可 (100% = 1) */
color: oklch(0.7 0.15 230 / 0.5); /* アルファ付き */| 成分 / Channel | 範囲 / Range | 意味 / Meaning |
|---|---|---|
| L (Lightness) | 0〜1(0%〜100%) | 知覚的明度。0 が黒、1 が白 |
| C (Chroma) | 0〜(sRGB では概ね 0.37 まで) | 彩度。0 で無彩色。上限は色相・明度に依存 |
| H (Hue) | 0〜360(deg) | 色相角。HSL の色相角とは一致しない |
注意点は2つ。第一に、H の値は HSL と互換性がありません(例: 青は HSL では 240、OKLCH では約 264)。 機械的に数値を移植せず、Color Converter で変換してください。 第二に、C を上げすぎると sRGB で表示できないガモット外の色になりますが、その場合も CSS は エラーにせず、ブラウザが表示可能な近い色へマッピングします。
OKLCH is the polar form of Oklab (Ottosson, 2020). Syntax: oklch(L C H / alpha). Hue angles do NOT match HSL hues, and out-of-gamut chroma is gamut-mapped by the browser rather than erroring.
3. ブラウザ対応とフォールバック / Browser support
| 機能 / Feature | Chrome / Edge | Firefox | Safari |
|---|---|---|---|
oklch() | 111+ (2023-03) | 113+ (2023-05) | 15.4+ (2022-03) |
color-mix(in oklch, ...) | 111+ | 113+ | 16.2+ |
相対カラー構文 (from) | 119+ | 128+ | 16.4+ |
2026年6月時点で、上記すべてが全モダンブラウザで利用可能です。 古い WebView や社内の固定バージョン環境を抱える場合だけ、CSS のカスケードを使った定石のフォールバックを入れます。
.button {
background: #3b82f6; /* 旧環境向けフォールバック */
background: oklch(0.623 0.214 259.8); /* 対応ブラウザはこちらを採用 */
}
/* 分岐が必要なら @supports でも判定できる */
@supports (color: oklch(0 0 0)) {
.badge { background: oklch(0.75 0.12 145); }
}As of 2026 every modern browser supports oklch(), color-mix() in OKLCH, and relative color syntax. For legacy WebViews, declare a hex value first and let the cascade pick oklch().
4. color-mix() と相対カラー構文で色を派生させる / Deriving colors
OKLCH が真価を発揮するのは色の派生です。sRGB 空間で色を混ぜると中間色が濁る (灰色がかる)ことがありますが、in oklch を指定すると知覚的に自然な中間色になります。
:root { --brand: oklch(0.623 0.214 259.8); }
/* hover / active を brand 色から派生させる */
.button:hover { background: color-mix(in oklch, var(--brand), white 20%); }
.button:active { background: color-mix(in oklch, var(--brand), black 15%); }さらに相対カラー構文(Relative Color Syntax)を使えば、混色ではなくL・C・H を直接演算して派生色を定義できます。
/* brand 色の L だけ +0.15(明るいバリアント) */
.brand-light { color: oklch(from var(--brand) calc(l + 0.15) c h); }
/* C を半分にして落ち着いたトーンに(色相・明度は維持) */
.brand-muted { color: oklch(from var(--brand) l calc(c * 0.5) h); }HSL で同じことをすると「L を足したら色相によって白飛びしたり、ほとんど変わらなかったり」という ムラが出ますが、OKLCH なら +0.15 がどの色相でもほぼ同じ「明るくなり方」になります。
color-mix(in oklch, ...) avoids the muddy midpoints of sRGB mixing, and relative color syntax lets you do arithmetic on L, C and H directly — a +0.15 lightness step looks the same at any hue.
5. デザインシステムでの採用 / Adoption in design systems
Tailwind CSS v4(2025年1月リリース)は、デフォルトカラーパレットの定義を OKLCH に切り替えました。 デザインシステムでの基本パターンは「H をほぼ固定し、L を段階的に動かしてシェイドを作る」です。
:root {
/* H を 259.8 に固定し、L 段階でシェイドを構成 */
--blue-300: oklch(0.81 0.10 259.8);
--blue-500: oklch(0.62 0.21 259.8);
--blue-700: oklch(0.46 0.18 259.8);
}L の刻みを揃えておけば、別の色相(green、red など)でも同じ L 値を使うだけで トーンの揃ったパレットになります。これは HSL では原理的に不可能だったことです。 ひとつ注意として、OKLCH の L 差は WCAG コントラスト比の保証にはなりません(コントラスト比は相対輝度ベースの別計算)。テキスト色の最終確認はColor Contrast Checker で行ってください。
Tailwind CSS v4 defines its default palette in OKLCH. Fix the hue, step the lightness, and you get tonally consistent shades across hues. Note that equal L steps do not guarantee WCAG contrast ratios — always verify text colors with a contrast checker.
まとめ / Summary
HSL の明度は sRGB の計算値にすぎず、色相をまたいだ明るさの統一には使えません。 OKLCH は L=知覚的明度という保証があるため、パレット設計・色の派生・テーマ生成のすべてが 予測可能になります。ブラウザ対応の心配は 2026 年時点で実質不要です。 新規のデザイントークンは OKLCH で定義し、既存の HSL は弱点が出る場面から順次置き換えるのが現実解です。
HSL looks intuitive but its lightness channel is a geometric artifact of the sRGB cube: pure yellow and pure blue both sit at L=50% while their relative luminance differs by a factor of 13. OKLCH, the polar form of the Oklab color space, makes lightness perceptually uniform, so the same L value looks equally bright at any hue. The CSS syntax is oklch(L C H / alpha), where L runs 0–1, chroma starts at 0 (about 0.37 max within sRGB), and hue is an angle that does not match HSL hues. Support has been universal since 2023 — Chrome 111, Firefox 113, Safari 15.4 — so in 2026 you can use it without hesitation, adding a hex fallback only for legacy WebViews. Combine it with color-mix(in oklch, ...) for clean hover states and with relative color syntax to derive variants by adjusting L or C directly. Tailwind CSS v4 already ships its palette in OKLCH; new design tokens should follow suit.
関連ツール / Related tools
- Color Converter - HEX / RGB / HSL / OKLCH 相互変換
- Color Picker - ブラウザで色を選んで各形式のコードを取得
- Color Contrast Checker - WCAG コントラスト比の検証