color theoryMay 3, 202612 min read

モダンCSSのOKLCHカラー:なぜ勝つのか、どう出荷するのか

CSSにおけるOKLCHカラーの実践ガイド。なぜhexは大規模運用で破綻したのか、OKLCHがどうやって明度のズレを解消するのか、4ステップの移行手順、そして2026年にすべてのデザインシステムが出荷すべき知覚的に均一なパレットランプまで。

By Boone
XLinkedIn
oklch color modern css

モダンCSSのOKLCHカラー:なぜ勝つのか、どう出荷するのか

OKLCHは、CSSが出荷した色空間の中で、デザイナーが初めて本当に理屈で扱えるものです。いまだにhexでパレットを組んでいるチームは、自分たちが戦っていることにすら気づかないまま、コントラストとダークモードの議論でひっそり負け続けています。

hexは色空間ではなく、シリアライズ形式だった

hexはsRGBの略記にすぎません。#4A90E2は色の仕様ではなく、赤・緑・青のチャンネル値を6文字に圧縮した3つ組です。sRGBは1990年代前半のCRTモニター向けに設計されたもので、人間の視覚知覚のために作られたものではありません。

その結果、パレット上で数値的に同じ「明るさ」の位置にある2つのhex値が、目にはまったく違って見えることが起こります。多くのデザインシステムで、blue-500はyellow-500より暗く見えます。ランプ上の相対位置が同じでもです。これはセンスの問題ではありません。座標系に焼き込まれた数学の問題です。

「hexは色空間ではなく、シリアライズ形式だった。そして私たちはそれ以来ずっと明度について言い争っている。」

HSLは直したふりをして、直さなかった

HSLが登場し、デザイナーに言葉を与えました。色相、彩度、明度。システムのように感じられました。でも違いました。HSLの明度チャンネルは内部ではsRGBの値にマッピングされているので、hexと同じ知覚上の問題をそのまま引き継いでいます。

hsl(220, 70%, 50%)とhsl(45, 70%, 50%)は、名目上は同じ明度です。並べて開いてみてください。黄色のほうが明らかに明るく見えます。HSLは、壊れた同じ数学に、よりマシな言葉を与えただけでした。

OKLCHは知覚的に均一

OKLCHは、Björn Ottossonが2020年に、従来の色空間の知覚的な不均一性に対処するために開発したOKLab色空間をベースにしています。OKLCHのLは知覚的な明度を表し、人間の視覚システムが実際に光へ反応する仕方に合わせて較正されています。

OKLCHで同じL値なら、知覚される明るさも同じです。ほぼ同じではありません。「彩度が近ければたいてい同じ」でもありません。同じです。これは過去のどのCSS色空間も実現できなかった性質であり、パレット生成の考え方をすべて変えます。

OKLCHが勝つ3つの理由

知覚的に均一な明度、予測可能な色相補間、そして広色域対応。それぞれが現在のパレットの特定のバグを直し、合わせるとテーマ、コンポーネント、ディスプレイの種類をまたいでスケールするカラーワークフローになります。

hexやHSLに対してOKLCHがもたらす3つの構造的な勝利(知覚的な明度、まともな色相補間、広色域への到達)を表す、3つの積み重なったブロックのボクセルコンセプト
hexやHSLに対してOKLCHがもたらす3つの構造的な勝利(知覚的な明度、まともな色相補間、広色域への到達)を表す、3つの積み重なったブロックのボクセルコンセプト

理由その1:明度のズレは死んだ

hexとHSLのシステムでは、明度のズレはあらゆるパレットに課される目に見えない税金です。blue-50とamber-50を目で見て良さそうな値に設定しても、画面ごとに差が開き、ダークモードで互いにぶつかり、コントラストの計算もきれいには成立しません。

OKLCHなら、blue-50とamber-50は同じ明度の数値になり、その数値は同じ知覚的な明るさを表します。Tailwind v4がパレット全体をOKLCHに移行したのは、まさにこの理由からです。Radix UIのカラースケールを使っているなら、ドキュメントでOKLCHという言葉を見たことがなくても、すでに知覚的な均一性の恩恵を受けています。

理由その2:色相補間がまともになる

sRGB補間を使うCSSのグラデーションは、知覚空間ではなくRGBカラーキューブの中を通ります。sRGBの青から黄色へのグラデーションは、RGBの対角線が無彩色軸の近くを横切るため、濁ったグレーの中間を通過します。芸術的なのではありません。幾何学上の事故です。

OKLCHのグラデーション補間は、知覚的なリングに沿って色相角を歩きます。OKLCHで青から黄色へ向かうとシアンと緑を通り、これは目が期待する通りの経路です。グレーの濁りは消えます。UIのグラデーション、アニメーションする色の遷移、中間ステップを生成するあらゆるパレット生成ツールで効いてきます。

理由その3:P3とRec2020に手が届く

hexはsRGBの外側の色を表現できません。2016年以降のすべてのiPhone、広色域パネルを積んだ最近のノートPC、そして新しい消費者向けモニターの大半は、P3色域には存在してもhexのアドレスを持たない色を表示できます。座標系がその色に名前を付けられなかったせいで、彩度の高い鮮やかな色をずっと取りこぼしてきたのです。

OKLCHならP3やRec2020の色をネイティブに記述できます。oklch(0.60 0.28 260)はP3には存在するもののsRGB色域の外にある鮮やかな青です。モダンブラウザはこれをきちんと扱えますし、AppleのDisplay P3に関するカラーガイダンスも、何年も前からこの方向を指しています。今OKLCHへ移行するデザインシステムは、P3が当たり前の期待値になったときにも準備ができているデザインシステムです。

hexからOKLCHへの4ステップ移行

監査、変換、再生成、再監査。この移行はプリミティブトークンでは機械的に進められ、セマンティックトークンでは判断が必要です。中規模のデザインシステムなら、全面移行は数週間ではなく数日で終わります。始める前に、新しいトークンをきちんとしたFigma variablesアーキテクチャに据えておくと、最も時間を節約できます。

ステップ1:既存パレットを監査する

システム内のすべてのカラートークンをエクスポートします。oklch.comやPostCSSのOKLCHプラグインのようなツールで、各hex値をOKLCHに変換します。L値でソートし、色相をまたいだ明度の列を眺めます。

バグはすぐに姿を現します。blue-300がL=0.72なのに、yellow-300はL=0.87にいる。同等の視覚的ウェイトのはずだったトークンが、まるで近くありません。この監査は、移行の判断に異を唱える誰に対しても、簡単に正当化できる証拠になります。

ステップ2:プリミティブをOKLCHに変換する

プリミティブスケール、つまりセマンティックトークンではなく生の番号付きランプを取り、OKLCHに変換します。明度の値は、11ストップすべてで一貫したステップに丸めます:0.97、0.93、0.86、0.75、0.65、0.54、0.45、0.37、0.27、0.19、0.13。

元のhex値をそのまま保とうとしてはいけません。目的は不整合を直すことです。変換後のblue-500とred-500は、旧値とピクセル単位で同一にはなりませんが、それこそが目的のすべてです。システムは、ただ変わるのではなく、良くなっているのです。

ステップ3:ランプを再生成する

明度のステップがきれいに揃えば、色相をまたいだランプの再生成は表計算のような作業になります。L列を設定し、各色相の彩度を選び(青は通常、クリップするまでに茶色や黄色より多くの彩度を持てます)、H列を調整して、生成します。

結果として、blue-500とred-500が、システム内で初めて同じ視覚的ウェイトに感じられるようになります。これまで恣意的な判断だったブランドカラーパレットの決定は、指し示せる座標を持つ、筋の通った選択に変わります。

ステップ4:アクセシビリティを再監査する

新しいパレットには、新しいコントラストの確認が必要です。OKLCHでは、明度が名前の通りの意味を持つので、コントラストの予測が楽になります。L値がわかっている2つのトークンを組み合わせれば、チェッカーを開く前から、コントラスト比について強い見立てが持てます。

すべてのセマンティックトークンの組み合わせに、WCAGとAPCAのコントラストチェックを実行します。要件を満たさなくなったペアにフラグを立て、失敗しているトークンの彩度か明度を調整します。OKLCHパレットに対する適切なアクセシブルなカラーコントラストの確認は、hexパレットでの同等の確認より、意外な発見が少なく済むのが普通です。以前は明度のステップがそもそも間違っていて、今はそうではないからです。


モード、色相、モダンなディスプレイをまたいで、明度のズレなしに持ちこたえるカラーシステムがほしいですか?BrainyはOKLCHネイティブのパレットシステムを設計します。Figma variables、CSSカスタムプロパティ、Tailwindトークンとして出荷され、コントラストの確認も済んでいます。


OKLCHの4つの落とし穴

色域外のクランプ、彩度のクリッピング、アルファの扱い、ツールの穴。どれもOKLCHに不慣れなチームに噛みつきますが、何を探せばいいかさえわかれば、どれも数分で当てられる具体的な対処法があります。

落とし穴何が起こるか対処法
色域外のクランプ高彩度の値がsRGBの外に出て、ブラウザにクランプされ、ときに色相がずれるP3専用の色は@media (color-gamut: p3)の内側に閉じ込める
彩度のクリッピングクランプは彩度だけでなく色相も少し変える幅広い互換性のため、sRGBで安全な彩度を約0.20未満に抑える
アルファの扱いoklch(0.55 0.20 260 / 0.5)は静的な塗りでは動くが、古いブラウザでは一部の補間経路が壊れる静的な色だけでなく、グラデーションやトランジションでもアルファをテストする
ツールの穴Figmaのネイティブなカラーピッカーは、OKLCHを直接は扱えないTokens Studioを使うか、トークンをCSSで定義してFigmaのコードパネル経由で参照する

色域の問題が最も痛いところです。oklch(0.60 0.32 260)と書くと、その彩度の値はsRGBの外側にあります。デスクトップブラウザは最も近いsRGBの色にクランプして対処しますが、見た目の色相がずれることがあります。対処法は、ベーストークンではsRGBで安全な彩度に留めるか、広色域の値をメディアクエリの内側に置き、その上にフォールバックの宣言を残すかのどちらかです。

実用的なOKLCHパレットランプ

一貫した明度ステップによる、実用的な11段階のランプです。基準には色相260の青を使っています。明度のステップは、システム内のどの色相でも同一です。色ファミリーごとに変わるのは、彩度と色相だけです。

css
:root { --blue-50: oklch(0.97 0.02 260); --blue-100: oklch(0.93 0.05 260); --blue-200: oklch(0.86 0.09 260); --blue-300: oklch(0.75 0.14 260); --blue-400: oklch(0.65 0.18 260); --blue-500: oklch(0.54 0.22 260); --blue-600: oklch(0.45 0.20 260); --blue-700: oklch(0.37 0.17 260); --blue-800: oklch(0.27 0.13 260); --blue-900: oklch(0.19 0.09 260); --blue-950: oklch(0.13 0.06 260); }

red(色相25)、amber(色相75)、green(色相145)を作るには、11ストップすべてでL列を同一に保ちます。Cは色相が本来持つ彩度の許容量に合わせて調整します。黄色や緑は、sRGBからはみ出す前に持てる彩度が青より少ないからです。Hは目標の色相に合わせます。これがパレットシステムのすべてです。

このランプの上に築くダークモードのカラーシステムは、hex値を一つずつ手作業で上書きするのではなく、LのステップとHueでプリミティブ間を切り替えるセマンティックトークンを使います。

ストップ全体で知覚的な明度が均一な11段階のカラーランプのボクセルコンセプト。OKLCHが50から950まで視覚的ウェイトを一貫させる様子を示す
ストップ全体で知覚的な明度が均一な11段階のカラーランプのボクセルコンセプト。OKLCHが50から950まで視覚的ウェイトを一貫させる様子を示す

ブラウザ対応と安全な移行の時期

OKLCHは2023年以降にリリースされたすべての主要ブラウザで対応しています。Chrome 111、Safari 15.4、Firefox 113、Edge 111のすべてが、OKLCHをフルサポートして出荷されています。2025年半ば時点で、グローバルのカバレッジは93%を超えています。移行の窓は開いています。

ブラウザOKLCH対応対応開始
Chromeフル111(2023年3月)
Safariフル15.4(2022年3月)
Firefoxフル113(2023年5月)
Edgeフル111(2023年3月)
Samsung Internetフル21(2023年)

OKLCH非対応のブラウザへのフォールバックは1行で済みます。先にhexのフォールバックを宣言し、そのあとでOKLCHの値を書きます。OKLCHを理解しないブラウザはそれを無視してhexを使い、理解するブラウザはより良い値を使います。

css
color: #4a7de8; /* sRGB fallback */ color: oklch(0.54 0.22 260); /* OKLCH for modern browsers */

Tailwind v4は、パレットをOKLCHでネイティブに生成します。Linear、Stripe Sailのデザイントークン、そしてAppleのデベロッパー向けカラーガイダンスも、すべて知覚的に均一なシステムへ向かっています。業界は着地しました。問題は、あなたのチームがいつ合流するかです。

FAQ

OKLCHは習得が難しいですか?

座標系はhexやHSLとは違いますが、複雑ではありません。Lは0から1までの明度。Cは彩度で、おおよその鮮やかさです。Hは度数で表す色相です。Lが知覚的な明るさ、Cが色の鮮やかさを意味すると腹落ちしてしまえば、HSLのときよりも早く直感的になります。

今日、FigmaでOKLCHを使えますか?

2025年時点で、FigmaはカラーピッカーでOKLCHをネイティブには扱えません。実用的なワークフローは、Tokens Studio経由のトークンファイル、またはFigma variablesに同期したCSS変数ファイルで、トークンをOKLCHで定義し、Figmaのコードエクスポートで値を確認することです。Figmaのレンダリングエンジンが内部で変換を処理します。

OKLCHは既存のhex値を壊しますか?

いいえ。OKLCHは、トークンごとに段階的に導入できます。既存のhex値は、これまでとまったく同じように動き続けます。移行は置き換えではなく、追加です。

LCHとOKLCHの違いは何ですか?

LCHはCIELAB色空間をベースにしています。これは知覚的に均一ですが、特に青紫の範囲で色相の線形性に問題があります。OKLCHはOKLabをベースにしており、その色相のずれを補正します。実務のデザインでは、色相補間による意外な結果が少ないため、OKLCHのほうが良い選択です。

hexをOKLCHに変換するには?

oklch.com、PostCSSのoklchプラグイン、またはCSS Color 4仕様のプレイグラウンドを使います。hex値を貼り付けてOKLCHの座標を読み取り、LとCは小数第2位に、Hは最も近い整数の度数に丸めます。それが実用上のトークン値です。

OKLCHはアクセシビリティ要件に影響しますか?

WCAGのコントラスト要件は、OKLCHの明度ではなく、sRGBの相対輝度に対して定義されています。APCAは知覚モデルにより近く、OKLCHのL値により自然に対応します。実際には、Lが知覚的な明るさに追従するので、OKLCHではコントラストの予測がより直感的になりますが、セマンティックトークンのペアをコントラストチェッカーにかける必要は変わりません。プロセスは同じで、事前に見通しを立てやすくなるだけです。

OKLCHが本当に解き放つもの

OKLCHは流行ではありません。人間の目が色をどう知覚するかを軸に設計された色空間を、CSSが初めて出荷したのであり、ツールも十分に追いついたので、数日を集中して費やす気のあるチームなら、今日から移行が現実的です。

今動くチームは3つを同時に手に入れます。手作業の上書きなしにダークモードで持ちこたえるパレット、座標系と一致するコントラストの挙動、そして将来の書き直しなしにP3へ広がる土台です。待つチームは、なぜblue-300がorange-300より重く見えるのかという同じ議論を、これからも続けることになり、その答えもやはり同じです。この座標系は、そんな仕事のために設計されていません。

このパレットの上に完全なトークンアーキテクチャを築きたいなら、Figma variablesアーキテクチャのペーパーがセマンティックレイヤーを扱っています。この作業のダークモードへの適用については、ダークモードのカラーシステムが、この記事の終わったところから始まります。

代わりに作ってほしいですか?Brainyに依頼する。

Want a color system that holds up across modes, hues, and modern displays without lightness drift? Brainy designs OKLCH-native palette systems that ship as Figma variables, CSS custom properties, and Tailwind tokens with the contrast pass already done.

Get Started

More from Brainy Papers

Keep reading