COLOR ON THE WEB

Web 平台的颜色:屏幕、规范与设备

2026-10-28 · AI 协作整理(Claude)

结论先行

Web 的颜色在 2016–2025 年间从“只有 sRGB”变成了“与设备无关的色彩空间 + 广色域 + 开始支持 HDR”。驱动力是硬件先变、规范和浏览器追赶:Apple 在 2015–2016 年把 Mac 和 iPhone 换成 Display P3 屏幕,CSS 当时却规定颜色只在 sRGB 里(WebKit 博客原话),于是 WebKit 先动手。

Web 颜色的两条线 · 1996–2026

左边的硬件与影像标准在 2015–2017 年密集变化,右边的 CSS 直到 2021–2023 年才集中跟上;HDR 则在 2025 年前后同时出现在两边。

屏幕特性

一块屏幕能显示什么颜色,由四件事决定:三个原色的位置(色域)、白点、传递曲线(数值怎么变成亮度)、以及亮度范围和位深。网页上的一个颜色值,只有说清楚是哪个空间里的坐标,系统才能把它换算到这块屏幕上。

人眼与参照系。 CIE 1931 根据 1920 年代 Wright 与 Guild 的配色实验定义了 XYZ,是与设备无关的参照。xy 色度图里两种光的混合落在连线上,所以三原色屏幕的色域是一个三角形。xy 不是感知均匀的,1976 年的 CIELAB 试图修正,2020 年的 Oklab 又修正了 CIELAB 在蓝色区的色相偏移。

色彩空间 年份 定义者 原色 / 传递曲线 占 CIE 1931 xy 面积
sRGB 1996(IEC 61966-2-1:1999) HP 与 Microsoft BT.709 原色、D65;分段曲线,约等于 gamma 2.2;参考亮度 80 cd/m² 35.9%
Display P3 2015 Apple DCI-P3 原色 + D65 + sRGB 曲线 53.6%(DCI-P3)
Rec.2020 2012 ITU-R 630 / 532 / 467 nm 单色原色;10 或 12 位 75.8%
Rec.2100 2016 ITU-R Rec.2020 原色 + PQ(SMPTE ST 2084)或 HLG 两种 HDR 曲线 同 Rec.2020

一个常见误解:Apple 说 P3 “饱和度高 25%”,是和 iPad Air 2 的比较,不是色域面积。按 xy 面积算,DCI-P3 约为 sRGB 的 1.5 倍。

CSS 颜色规范的变迁

CSS 颜色经历了四代:关键词和十六进制(CSS1)、更便于人写的 sRGB 写法(Color 3)、与设备无关的色彩空间(Color 4)、颜色运算与 HDR(Color 5 和 Color HDR)。前三代的所有写法都只是 sRGB 的不同拼法。

规范 状态与年份 新增 备注
CSS1 1996 16 个基本关键词、#rgb / #rrggbb、rgb() 关键词来自 HTML;CSS2 加了 orange
CSS2 1998 28 个系统颜色(ButtonFace、WindowText 等) Color 3 废弃了它们,后来以 CSS system colors 的形式保留一部分
CSS Color 3 2011 REC rgba()、hsl()、hsla()、transparent、currentColor、147 个 X11 命名色 明确“RGB 即 sRGB”;X11 名字里 darkgray 比 gray 还浅
CSS Color 4 2022 CR lab()、lch()、oklab()、oklch()、hwb()、color()、none、空格语法、rebeccapurple color() 的预定义空间:srgb、srgb-linear、display-p3、a98-rgb、prophoto-rgb、rec2020、xyz-d50、xyz-d65;规定色域映射
CSS Color 5 工作草案(2026-06) color-mix()、相对颜色语法 from、light-dark()、contrast-color()、device-cmyk()、@color-profile color-mix() 不指定空间时默认 Oklab
CSS Color HDR 1 工作草案(2024-12 起) dynamic-range-limit、hdr-color()、ictcp()、jzazbz()、rec2100-pq / hlg / linear 编辑 Chris Lilley;HDR 参考白 203 cd/m²

同一个“红”在各代规范里的写法:

/* CSS1:关键词与十六进制,都是 sRGB */
color: red;  color: #f00;  color: rgb(255, 0, 0);

/* Color 3:透明度与 HSL,仍是 sRGB */
color: rgba(255, 0, 0, .5);  color: hsl(0 100% 50%);

/* Color 4:指明色彩空间,可以超出 sRGB */
color: color(display-p3 1 0 0);      /* P3 屏上更饱和的红 */
color: oklch(62.8% 0.258 29.2);      /* 亮度 / 色度 / 色相 */
color: lab(54.3% 80.8 69.9);

/* Color 5:由已有颜色算出新颜色 */
color: color-mix(in oklab, red 60%, white);
color: oklch(from var(--brand) calc(l + .1) c h);
color: light-dark(#222, #eee);
color: contrast-color(var(--bg));    /* 黑或白 */

/* HDR:限制页面里 HDR 内容的亮度 */
img { dynamic-range-limit: standard; }

/* 按屏幕能力分支 */
@media (color-gamut: p3) { … }
@media (dynamic-range: high) { … }

为什么要 OKLCH。 HSL 的“亮度 50%”对黄色和蓝色看起来完全不同;sRGB 里蓝到白的渐变会发紫。Oklab 的目标是等距离就是等感知差距,所以改亮度不会带动色相,生成调色板和渐变更稳定。2021 年 9 月 Chris Lilley 开了 CSSWG issue #6642,10 月 13 日工作组决议加入 oklab() / oklch(),并把 Oklab 定为非传统颜色的默认插值空间。

色域映射的争论。 一个 oklch 颜色可能超出屏幕色域。规范描述了裁剪、降低色度等做法,但浏览器一开始都直接逐通道裁剪,色相会变。issue #9449(2023)批评这“破坏了 oklch 的意义”;2024 年 Chrome 的 Christopher Cameron 开 #10579 比较更快的静态映射算法,讨论仍在继续。

各种颜色表示的差异

这些写法的差别在三件事:坐标轴指什么、能不能超出 sRGB、坐标上的等距是不是看起来的等距。前三种只是 sRGB 的换写,lab / oklab 系与设备无关,color() 是“指明哪个 RGB 空间”。

写法 三个坐标 能表示的范围 感知均匀 常见坑
#rrggbb、rgb() 红、绿、蓝的编码值 0–255 只有 sRGB 否 数值是伽马编码后的,不是光强;数值的中点不是亮度的中点
hsl() 色相角、饱和度、“亮度” 只有 sRGB 否 亮度 50% 的黄色和蓝色看起来差很远(OKLCH 亮度 0.97 对 0.45)
hwb() 色相、混入的白、混入的黑 只有 sRGB 否 类似取色器的想法,问题同 HSL
lab()、lch() 亮度 L 0–100,a/b 或色度/色相;D50 白点 所有可见色 大体 蓝紫区改变亮度或色度时色相会漂(蓝变紫)
oklab()、oklch() 亮度 L 0–1,色度 C(实用上限约 0.37),色相 H;D65 所有可见色 更好 同一亮度下不同色相的最大色度不同,很容易写出色域外的颜色
color(display-p3 …) 等 指定空间里的 R G B,0–1 该空间的三角形 否 同样的数字在不同空间是不同的颜色

同一个颜色 rebeccapurple 的各种写法(由 sRGB 换算),以及一个 sRGB 写不出来的红:

color: #663399;
color: rgb(102 51 153);
color: hsl(270 50% 40%);
color: hwb(270 20% 40%);
color: lab(32.39% 38.42 -47.69);
color: oklch(44.0% 0.160 303.4);
color: color(display-p3 0.374 0.210 0.579);   /* 同一个颜色,P3 坐标不同 */

/* P3 的最红:换到 sRGB 是 (1.093, -0.227, -0.150),超出范围 */
color: color(display-p3 1 0 0);                /* oklch(64.9% 0.300 29.0) */
color: red;                                    /* oklch(62.8% 0.258 29.2) */

插值也不同。 同样从红到蓝,渐变在哪个空间里算,结果差很多:

linear-gradient(in srgb,  red, blue)   /* 中间发暗、发灰的紫 */
linear-gradient(in oklab, red, blue)   /* 亮度平顺,中间是偏亮的紫 */
linear-gradient(in oklch, red, blue)   /* 沿色相环走,经过品红,饱和度不掉 */
linear-gradient(in oklch longer hue, red, blue)   /* 绕远路,经过黄和绿 */

浏览器实现与色彩管理

Safari 先行、Chrome 和 Firefox 在 2023 年一起追平:Interop 2022 与 2023 都把“色彩空间与颜色函数”列为重点,2023 年 5 月 Lab / LCH / Oklab / OKLCH 在三大引擎互通。

特性 Safari Chrome / Edge Firefox Baseline
color-gamut 媒体查询 10 58 110 2023
dynamic-range 媒体查询 13.1 98 100 2022
lab() lch() color() hwb() 15(2021-10) 111(2023-03) 113(2023-05) 2023-05
oklab() oklch() 15.4 111 113 2023-05
color-mix() 16.2(2022-12) 111 113 2023-05
相对颜色语法 from 18 119 128 2024
light-dark() 17.5 123 120 2024-05
contrast-color() 26 147 146 2026-04
dynamic-range-limit 26(不含 constrained) 136(2025-04) — 未达

色彩管理的历史比 CSS 语法更曲折。 关键问题是“没有标注色彩空间的内容怎么办”:当作 sRGB 换算到屏幕,还是把数值直接交给屏幕。后者在广色域屏上会过饱和。

待核对:color(display-p3) 在 Safari 里确切的首个版本(2020 年 WebKit 博客说 macOS Mojave / iOS 11 起可用);Chrome 全面色彩管理在各平台的版本。

Canvas、WebGPU、图片与视频

像素接口比 CSS 更难升级,因为它们直接暴露数组:每个像素是哪个空间、各占几位,都要写进 API。

// 2D Canvas:Chrome 94;Safari(macOS 12.1 / iOS 15.1)
const ctx = canvas.getContext('2d', { colorSpace: 'display-p3' });
ctx.fillStyle = 'color(display-p3 1 0 0)';
const img = ctx.getImageData(0, 0, w, h, { colorSpace: 'display-p3' });

// WebGL:Baseline 2024
gl.drawingBufferColorSpace = 'display-p3';

// WebGPU HDR:Chrome 129,允许超过 1.0 的值
context.configure({ device, format: 'rgba16float',
                    toneMapping: { mode: 'extended' } });

// 视频:解码前询问能力
navigator.mediaCapabilities.decodingInfo({ type: 'media-source',
  video: { contentType: 'video/mp4; codecs="hvc1"', width: 3840, height: 2160,
           bitrate: 2e7, framerate: 30,
           transferFunction: 'pq', colorGamut: 'rec2020', hdrMetadataType: 'smpteSt2086' } });

谁在推动

推动力主要来自这几类人:硬件厂商制造需求,规范编辑和浏览器工程师设计语法,色彩科学家提供模型,影像行业带来 HDR 标准,设计工具与框架把它们交到普通开发者手里。无障碍社区则在对比度上提出另一组要求。

群体 代表 做了什么
早期网页与设计书 Netscape、Lynda Weinman 256 色显示器时代的 216 色“浏览器安全色”;Weinman 1996 年的书让它普及
操作系统厂商 HP + Microsoft;Apple;Google Android;Microsoft Windows 1996 年提出 sRGB;2015 年 Display P3 与全线广色域屏;2017 年 Android 广色域、Ultra HDR;2022 年 Windows 自动色彩管理
W3C 与规范编辑 Chris Lilley(W3C,PNG 合著者)、Tab Atkins(Google)、Lea Verou、Una Kravets 编写 Color 4 / 5 / HDR;Lilley 与 Verou 做了 Color.js(2022 公开),作为规范的参考实现
浏览器工程师 WebKit 的 Dean Jackson、Simon Fraser、Sam Weinig;Chrome 的 Christopher Cameron、Ken Russell;Igalia;Mozilla 2016 年 WebKit《Improving Color on the Web》;Cameron 提出 dynamic-range-limit、HDR Canvas、色域映射算法;Interop 2022 / 2023
色彩科学 Björn Ottosson 2020-12-23 发布 Oklab;动机是游戏开发里简单的变亮变暗;Photoshop 渐变也改用 Oklab
影像与广播 BBC、NHK、Dolby、Netflix、Disney、Adobe、ISO HLG 与 PQ(BT.2100,2016)、HDR10、Dolby Vision;增益图标准 ISO 21496-1
设计工具与框架 Sketch 48(2017)、Figma(2024)、Evil Martians、Radix Colors 3(2023)、Open Props、Tailwind v4(2025) 设计稿可以是 P3;文章《OKLCH in CSS》(2022)与 oklch 取色器;默认调色板改用 oklch
无障碍社区 WCAG、Andrew Somers(APCA) WCAG 2 的对比度公式建立在 sRGB 上;APCA 曾进入 WCAG 3 草案,2023 年被移除,算法至今未定

两个关键场合:

一个小插曲:rebeccapurple(#663399)2014 年 6 月由 Daniel Glazman 提议,纪念 Eric Meyer 早逝的女儿 Rebecca,工作组两天内达成共识,四家浏览器都承诺实现。

其他设备

手机已经是广色域与 HDR 的主力,头显的硬件也在 P3 附近;但 WebXR 规范里只有 sRGB,网页在头显里的颜色还很原始。

设备 显示 色域 / 亮度 与 Web 的关系
iPhone / iPad OLED、mini-LED(XDR) P3;EDR 余量约 8–16 倍 Safari 最早支持 P3 CSS 与 Canvas;Safari 26 支持 HDR 图片
Android 手机 OLED 为主 8.0 起可申请广色域;14 起 Ultra HDR 拍照 Chrome 显示 Ultra HDR / ISO 增益图
Apple Vision Pro micro-OLED,约 2300 万像素 92% DCI-P3;支持 Dolby Vision、HDR10、HLG 播放 visionOS 2 的 Safari 默认开启 WebXR,仅 immersive-vr
Meta Quest Quest 3 为 LCD + pancake 透镜 系统默认:初代 Quest Rec.2020,Quest 2 Rec.709;Quest 3 未公布 原生 SDK 要求应用声明内容所用的色彩空间,由系统换算
Samsung Galaxy XR(2025) micro-OLED 约 90% DCI-P3 Android XR 上的 Chrome
HDR 电视 OLED、QD-OLED、mini-LED HDR10(PQ,Rec.2020 容器)、Dolby Vision、HLG 主要通过流媒体 App,网页中的 HDR 视频依赖 MediaCapabilities
彩色电子墨水 E Ink Kaleido 3(2022) 4096 色、16 级灰;彩色 150 ppi 浏览器仍按 sRGB 渲染,饱和度远低于 sRGB
智能手表 LTPO OLED Apple Watch Ultra 3 最亮 3000 nits 没有浏览器

XR 平台

头显屏幕已经覆盖 90% 以上的 DCI-P3,原生应用可以用 P3 甚至 HDR;但网页只有在“平面网页”里用得到这些能力,进入 WebXR 沉浸模式后仍只有 sRGB。

平台 显示 浏览器里的颜色能力 WebXR
visionOS 26(Vision Pro) micro-OLED,92% DCI-P3;视频支持 Dolby Vision / HDR10 / HLG Safari 26:HDR 图片、dynamic-range-limit、WebGPU、<model> 元素(USDZ,可用 .exr / .hdr 环境光照)、空间视频与 180°/360° 视频 visionOS 2 起默认开启,只有 immersive-vr;immersive-ar 返回不支持,网页不能叠加在透视画面上
Android XR(Galaxy XR,2025-10) micro-OLED,约 90% DCI-P3 Chrome 支持 immersive-ar、命中测试、深度感知、光照估计
Meta Horizon OS(Quest 3) LCD;两个 4MP 彩色透视摄像头 Quest Browser 支持 immersive-ar:透明像素处显示现实画面,脚本拿不到透视像素

打印。 CSS Color 5 的 device-cmyk() 和 @color-profile 是给打印准备的,目前都被标为“有风险”(at risk),可能从规范中移除。

视频提纲

建议分两集,每集约 7–8 分钟,沿用前几期的形式:页面信息密度高、多放代码和关系图。这个题目可以在画面里直接画颜色:用 Canvas 绘制色度图和渐变对比(视频本身是 sRGB / BT.709,超出 sRGB 的颜色只能用标注示意)。

上集 · 屏幕与规范

  1. 开场:同一个 #ff0000,在 2010 年的显示器和今天的手机上不是同一种红。
  2. 人眼与 CIE 1931:马蹄形色度图,为什么屏幕色域是三角形。动画:sRGB、P3、Rec.2020 三个三角形依次叠上,标出 35.9% / 53.6% / 75.8%。
  3. sRGB(1996):HP 与 Microsoft 把 CRT 的平均值写成标准。动画:传递曲线与 80 cd/m²。
  4. 256 色时代:216 色安全色(6×6×6 立方体动画)、Lynda Weinman。
  5. CSS1 到 Color 3:代码卡——关键词、hex、rgba、hsl;X11 命名色的怪事(darkgray 比 gray 浅)、rebeccapurple。
  6. 屏幕变了:2015 年 iMac P3、量子点、OLED;WebKit 2016 年“CSS 只在 sRGB 里”。关系图:硬件 → 系统色彩管理 → 浏览器 → CSS。
  7. CSS Color 4:color()、lab()、oklch() 代码卡;“色彩空间 + 坐标”的表示法。
  8. 为什么是 Oklab:HSL 等亮度色条、sRGB 与 Oklab 的蓝到白渐变对比;Ottosson 2020 年博客到 CSSWG 2021 年决议。
  9. 浏览器时间线:Safari 15 → Chrome 111 → Firefox 113,Interop 2022 / 2023。
  10. 小结与下集预告。

下集 · HDR、设备与推动者

  1. 开场:一张 HDR 照片旁边的白字为什么发灰。
  2. 色域映射:逐通道裁剪 vs 在 OKLCH 里降低色度(动画:一个超出三角形的点被拉回来);issue #9449 与 #10579。
  3. Color 5:color-mix()、from 相对颜色、light-dark()、contrast-color(),从一个品牌色生成整套调色板。
  4. 色彩管理:未标注内容的两种处理;Firefox mode 2;Windows 自动色彩管理。
  5. HDR 基础:PQ 与 HLG、参考白 203 nits、EDR 余量(动画:亮度柱从 SDR 白向上长出)。
  6. HDR 进入网页:增益图(Ultra HDR → ISO 21496-1)、dynamic-range-limit、WebGPU extended、float16 Canvas、MediaCapabilities。
  7. 其他设备:手机、电视、Vision Pro、Quest、彩色墨水屏;WebXR 只有 sRGB。
  8. 谁在推动:关系图——厂商、W3C 与编辑、浏览器工程师、色彩科学、影像行业、设计工具、无障碍;2021 年 W3C 研讨会。
  9. 还没解决的事与给开发者的建议:用 oklch 写调色板、@media (color-gamut: p3) 渐进增强、对比度仍按 WCAG 2 检查。
  10. 结尾。

参考资料

规范

浏览器与平台

人物与社区

设备与色彩科学

未能从原始页面核对的:Safari 首次支持 color(display-p3) 的版本、Chrome 各平台全面色彩管理的版本、float16 Canvas 的发布状态、CSS 最终采用的色域映射算法。

Markdown 原文与视频稿件:sources/web-color。返回目录