你以为设计稿里的 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 的性能差异可以忽略不计。真正有影响的是:
- 宽色域图像:如果你的图片用了 P3 ICC profile,浏览器渲染时要做色彩管理转换,略微增加 GPU 开销
- 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 自己接上了。
评论区
登录后可评论。