在过去二十余年里,前端工程师与 UI 设计师几乎完全被囚禁在 sRGB 色彩空间#RRGGBBrgb()hsl() 三种表示法构建的“色彩孤岛”中。

然而,每当你尝试在设计系统中构建一套自适应的主题调色板或无障碍高对比度方案时,传统的色彩模型总是充满反直觉的坑:

  • 为什么在 HSL 中,把明度(Lightness)统一设为 50%,纯黄色(hsl(60, 100%, 50%))亮得刺眼、白底黑字清晰可见,而纯蓝色(hsl(240, 100%, 50%))却暗得像墨水、完全看不清文字?
  • 为什么苹果 iPhone 和 Mac 屏幕早已标配 Display P3 广色域,但网页里的红绿图标依然显得黯淡发灰?
  • 为什么在深色模式(Dark Mode)自动推导背景色时,调出来的渐变色中间总会莫名其妙出现一层脏兮兮的灰色死区(Gray Dead Zone)?

为了彻底解决这些历史物理与生理感知缺陷,W3C 在 CSS Color Module Level 4 & 5 中引入了新一代基于人类视觉感知的色彩空间 —— OKLCHDisplay P3

本文结合本站色彩格式转换工具的底层换算逻辑,深入探讨这场从物理发光到人眼神经感知的色彩革命。


1. 传统 sRGB 与 HSL 的阿喀琉斯之踵

1996 年的老旧遗产:sRGB

sRGB 是微软与惠普在 1996 年制定的标准,最初是为了适配当时发光特性极其有限的阴极射线管(CRT)显示器。 它的色域范围非常狭窄,仅能覆盖人眼可见光谱(CIE 1931 色品图)的约 35%

       CIE 1931 人眼可见全光谱 (~100%)
      ┌─────────────────────────────────┐
      │  Display P3 色域 (~50%)          │
      │    ┌───────────────────────┐    │
      │    │  传统 sRGB 色域 (~35%) │    │
      │    │    ┌─────────────┐    │    │
      │    │    │ 历史网页色   │    │    │
      │    │    └─────────────┘    │    │
      │    └───────────────────────┘    │
      └─────────────────────────────────┘

今天,无论是最新的手机 OLED 屏幕、高端电竞显示器还是 MacBook 的 Liquid Retina 屏,硬件硬件本身都能轻松显示多出近 50% 的鲜艳色彩。但在过去很长一段时间里,网页 CSS 却根本没有语法能够调用这些更鲜活的颜色。

HSL 的“伪科学明度”与视锥细胞生理学

为了解决 RGB 三原色不够直观的问题,上世纪 70 年代计算机图形学发明了 HSL(色相、饱和度、明度)。但 HSL 的明度计算仅仅是一个机械的算术平均公式:

L=max(R,G,B)+min(R,G,B)2L = \frac{\max(R, G, B) + \min(R, G, B)}{2}

这个公式完全忽略了人类视网膜中感光细胞的生理特性:人眼的视网膜拥有感受红、绿、蓝三种波长的视锥细胞,其中对绿色和黄绿波长(约 555nm)的敏感度极高,而对纯蓝波长的敏感度极低

当你在 HSL 中取 L=50%L = 50\% 时:

  • 纯黄色 #FFFF00hsl(60, 100%, 50%)):人类感知相对亮度高达 92.7%
  • 纯蓝色 #0000FFhsl(240, 100%, 50%)):人类感知相对亮度仅有 7.2%

两者在 HSL 表面上拥有完全相同的“50% 明度”,但实际视觉感受却天差地别。这直接导致了:你根本无法用 HSL 批量推导具有稳定对比度的 UI 组件阶梯


2. OKLCH 的诞生:什么是“感知均匀性”?

为了建立一个符合人眼真实感官的色彩模型,科学家们先后推导了 CIE Lab、CIECAM02,并在 2020 年由瑞典工程师 Björn Ottosson 正式提出了 Oklab 色彩空间(以及基于极坐标的 OKLCH)。

OKLCH 由三个核心参数定义:oklch(L C H)

维度 含义 取值范围 特性与优势
L (Lightness) 感知明度 0%(纯黑)到 100%(纯白) 严格感知均匀:无论色相如何变化,相同 L 值的人眼明度感受完全一致!
C (Chroma) 彩度/纯度 理论无上限,日常屏幕约 0 ~ 0.4 从纯灰(C=0C=0)向外无限辐射,完美包容未来的超广色域显示硬件
H (Hue) 色相环角度 0360(deg) 0 对应粉红、90 对应黄绿、140 对应纯绿、260 对应天蓝

感知均匀(Perceptually Uniform)的震撼演示

如果在 OKLCH 中将感知明度固定为 0.7(70%),并将色相从 0 到 360 旋转: 无论你转到黄色、青色、品红还是深蓝,所有的颜色在视觉上都会呈现完全一致的明度! 如果将这些颜色同时去色转为黑白灰度图,它们的灰度深浅是完全相等的,彻底告别了 HSL 中“忽明忽暗”的滑稽体验。

/* 两者在人类眼中拥有严格一致的明暗感与文字可读性 */
--brand-yellow: oklch(0.7 0.18 95);
--brand-blue:   oklch(0.7 0.18 250);

3. 广色域 Display P3:网页色彩打破次元壁

在现代 CSS 中,通过引入原生广色域空间,我们终于可以在高端显示设备上展示更具冲击力的高饱和度色彩:

/* 传统 sRGB 能够表达的最红边缘 */
--legacy-red: rgb(255 0 0);

/* Display P3 广色域下的极致鲜红(在 OLED 屏幕上令人惊艳) */
--p3-red: color(display-p3 1 0 0);

/* 使用 OKLCH 表达并自动匹配设备能够支持的最大色域 */
--modern-neon-green: oklch(0.85 0.32 142);

色域映射(Gamut Mapping)与优雅降级

如果在一个普通千元机或老款办公显示器(仅支持 sRGB)上访问使用了超出 sRGB 色域的颜色,会发生什么?

传统做法是硬生生截断 RGB 坐标(Clipping),导致颜色严重偏色或失真。 而现代浏览器的 CSS 规范内部实现了基于 Oklab 的 Gamut Mapping(色域映射算法): 浏览器会保持该颜色的色相(H)与感知明度(L)完全恒定,仅顺着感知均匀的直线将彩度(C)适度缩减,将其优雅地投影到当前显示器所能承载的物理边界内!

这意味着:在 P3 屏幕上看到的是极其鲜亮的新世界,在老旧 sRGB 屏幕上依然自然和谐,绝不偏色。


4. 实战:利用相对颜色语法(Relative Colors)重构主题

现代 CSS(Chrome 119+, Safari 16.4+, Firefox 128+)原生支持相对颜色语法(Relative Color Syntax),它彻底终结了以往必须依赖 Sass/Less 预处理器 darken() / lighten() 的时代:

:root {
  /* 基础品牌主色 */
  --primary: oklch(0.6 0.22 260);

  /* 悬停态:保持色相和纯度,精确提升 8% 的人眼感知明度 */
  --primary-hover: oklch(from var(--primary) calc(l + 0.08) c h);

  /* 按下态:感知明度降低 6% */
  --primary-active: oklch(from var(--primary) calc(l - 0.06) c h);

  /* 柔和背景色:明度提升至 95%,彩度降低至原来的 15% */
  --primary-subtle: oklch(from var(--primary) 0.95 calc(c * 0.15) h);

  /* 自动互补对比色:色相环直接旋转 180 度,明度依然分毫不差! */
  --primary-complement: oklch(from var(--primary) l c calc(h + 180));
}

5. 无障碍对比度考量:从 WCAG 2.1 到 APCA

在设计 Web 系统时,无障碍访问(a11y)中的对比度(Contrast Ratio)一直受到严格监管。

  • WCAG 2.1 算法缺陷: 现行 WCAG 2.1 的对比度公式 (L1+0.05)/(L2+0.05)(L_1 + 0.05) / (L_2 + 0.05) 同样基于过时的 sRGB 相对亮度假设。在深色模式下,经常会出现“公式计算通过 4.5:1,但人类肉眼依然看不清细字体”的窘境。
  • 新一代 APCA(Accessible Perceptual Contrast Algorithm): 未来的 W3C WCAG 3.0 正全面拥抱基于人类感知的 APCA 算法。APCA 将文字的字号大小(Font Size)、字重粗细(Font Weight)与现代感知色彩空间绑定,计算出连续的轻度感知对比度数值(Lc)。

在过渡期,使用 OKLCH 保证明度差 ΔL0.45\Delta L \ge 0.45,就能在几乎所有常规界面中天然获得通过 WCAG AA 甚至 AAA 级的极佳可读性。