你以为设计稿里的 P3 色值在用户屏幕上还是同一个色?今天 CSS color() 把这件事彻底原生化了

配了三年设计系统,每次设计师给了一个 P3 色域的标注,你在代码里只能默默转成 sRGB hex——因为 CSS 一直没这个能力。今天这件事被 CSS color() 函数彻底原生化了。

问题:你的品牌红,在用户屏幕上根本不是同一个红

iPhone 7 以来的所有苹果设备、三星 Galaxy S10 以后的旗舰安卓机、MacBook Pro 2016 款之后的机器,它们的屏幕能显示的颜色范围(P3 色域)比普通 sRGB 屏幕大约多 25%。最明显的是饱和绿色和红色——设计稿里那个鲜艳的品牌红,在 P3 屏上本来应该更 Vibrant,但你只能输出一个被截断过的 sRGB 版本。

CSS 历史上所有颜色函数(hex/rgb/hsl/oklch)都隐式地在 sRGB 色域里工作,你没有办法直接说「我要 Display P3 里的这个红」。

方案:color() 函数,指定色域再给值

CSS Color Level 4 引入的 color() 函数改变了这个前提:

/* 声明式指定色域 */
color(display-p3 1 0 0);  /* 比 sRGB 更鲜艳的红 */
color(rec2020 0.42 0.36 0.91);  /* 更宽色域 */

/* 配合 CSS 自定义属性做语义化 */
:root {
  --brand: oklch(60% 0.2 25);
}
.btn-primary {
  background: var(--brand);
  background: color(display-p3 from var(--brand) r g b);  /* 提升到 P3 */
}

色域不是你想开就能开的——用户的屏幕必须支持。所以正确姿势是先给 sRGB fallback,再渐进增强

.brand-red {
  color: #c84b1f;  /* sRGB fallback,所有浏览器认识 */
  color: color(display-p3 0.78 0.3 0.13);  /* P3 增强,浏览器自动判断是否渲染 */
}

浏览器会优先用最下面一行能理解的值。不支持 color() 的浏览器直接忽略第二行,显示第一行 sRGB 色。不需要 @supports 包裹,CSS 声明顺序本身就是降级机制。

核心色域对比

色域 覆盖范围 典型设备 CSS 写法
sRGB ~35% 可见光 普通显示器/旧手机 hex/rgb/hsl 默认
Display P3 ~45%,比 sRGB 大 25% iPhone 7+/MacBook Pro 2016+ color(display-p3 r g b)
Rec.2020 ~75%,影视标准 部分高端电视/监视器 color(rec2020 r g b)

P3 的优势集中在高饱和色:纯红、绿、青色在 P3 屏上明显更鲜艳。低饱和色(马卡龙粉、浅灰)在两者之间几乎无差异。

浏览器支持:2026 年四大浏览器全部稳定

  • Chrome/Edge 111+(2023 年 3 月)
  • Firefox 113+(2023 年 5 月)
  • Safari 15+(2016 年,Safari 最先支持)
  • 覆盖全球约 96%+ 用户

检测用户屏幕是否支持 P3,可以用媒体查询:

/* 仅在 P3 屏幕增强 */
@media (color-gamut: p3) {
  .brand-vibrant { color: color(display-p3 0.78 0.3 0.13); }
}

实际性能:会变慢吗?

不会。CSS 颜色解析在浏览器层面完成,color() 相对于 hex 的性能差异可以忽略不计。真正有影响的是:

  1. 宽色域图像:如果你的图片用了 P3 ICC profile,浏览器渲染时要做色彩管理转换,略微增加 GPU 开销
  2. OLED 屏幕功耗:P3 的高饱和色在 OLED 上比 sRGB 更耗电——这才是需要在意的地方

三个坑

1. 设计稿导出色值必须带 ICC profile
如果你从 Figma 导出 P3 色值,Figma 的 Color Profile 必须设为 Display P3(File → Document Settings → Color Profile)。默认是 sRGB,转出来的 hex 值依然是 sRGB 色。

2. 截图表格里看不出差别
在 sRGB 屏幕上截图,再发到 P3 屏幕上看,差异消失——这不是 bug,是色彩管理的一部分。实测要肉身带着 P3 设备。

3. OKLCH 高 chroma 值天然就是 P3 色
oklch() 的色域上限由浏览器 gamut mapping 控制,高 chroma 值(c > 0.15)的 OKLCH 颜色在 P3 屏上显示范围远超 sRGB。你不需要主动转 P3——OKLCH 本身就穿透了色域限制。

三步下一步

第一步(5 分钟):把品牌主色改成 sRGB fallback + P3 增强两层声明,用 @media (color-gamut: p3) 做精准增强

第二步:把设计稿 Color Profile 切到 Display P3,让标注值和代码值在同一坐标系

第三步:用 Chrome DevTools 的 Rendering 面板模拟 P3 渲染(More Tools → Rendering → Show P3 coverage),肉眼确认哪些色块在 P3 下有实际提升


color() 解决的不是「CSS 能不能显示更多颜色」——而是你终于可以在代码里声明「我要 Display P3 里的这个颜色」,而不是靠设计稿截图猜值、设计稿导出 hex 后发现和标注差了一截。色域的 Gap,今天被 CSS 自己接上了。

评论区

0 条评论

登录后可评论。