配了五年设计系统,每次调完色值都要靠设计稿还原——今天 CSS 用一个函数把这件事彻底原生化了

设计师在 P3 屏幕上花了两小时调一个品牌紫,导出来你发现跟你代码里的 #8b5cf6 根本不是一回事。用户用 iPhone 15 看你的页面,设计师用 MacBook Pro 调的颜色——两个设备根本不在同一个色域里。

这不是你的问题。这是 CSS 长期只能处理 sRGB 这个 35% 可见光谱的色域,而现代设计工具从第一天起就跑在 P3(45-50% 可见光谱)上的断层。

color() 函数就是来解决这个断层的。


color(display-p3):让 CSS 直接输出广色域

color() 是 CSS Color Level 4 引入的通用颜色函数,它的核心能力是指定在哪个色彩空间里解释这组数字。写法很简单:

/* 显式声明在 display-p3 色域里解释这组数字 */
.brand-purple {
  color: color(display-p3 0.485 0.256 0.887);
}

/* 渐变里同理 */
.hero-gradient {
  background: linear-gradient(
    color(display-p3 0.9 0.2 0.1),
    color(display-p3 0.2 0.5 0.95)
  );
}

关键点:这里的数字是小数形式 (0.0-1.0),不是 sRGB 里的 0-255。把 sRGB 的十六进制直接扔进去,会映射到 P3 坐标系里完全不同的位置,颜色反而失真。

必须用专业工具导出真实的 P3 色值,不能靠换算。

截至 2026 年,color(display-p3) 全球覆盖率 93.54%,Chrome 111+、Firefox 113+、Safari 15+、Edge 111+ 均已支持。


Relative Color Syntax:CSS 自己会派生颜色了

color() 的另一个杀手级能力是相对颜色语法(CSS Color Level 5)。它的作用是从一个已有颜色推导出新颜色,不需要 Sass,不需要 JS:

:root {
  --brand: oklch(55% 0.21 260);
}

/* 派生一个亮色变体 */
--brand-light: oklch(from var(--brand) calc(l + 0.2) c h);

/* 派生一个暗色变体 */
--brand-dark: oklch(from var(--brand) calc(l - 0.15) c h);

/* 色相旋转 180 度(互补色)*/
--brand-complement: oklch(from var(--brand) l c calc(h + 180));

/* 降低饱和度 */
--brand-muted: oklch(from var(--brand) l calc(c - 0.1) h);

这意味着设计 token 的派生逻辑可以完全在 CSS 里完成,不再需要 Sass 的 lighten()darken(),也不需要 JS 运行时计算。浏览器兼容性:Chrome 119+、Firefox 128+、Safari 16.2+。


三个坑

坑一:色值必须用 P3 原生值,不能从 sRGB 换算

最常见的错误是把 sRGB 色值直接塞进 color(display-p3)。比如设计师的 P3 红和 sRGB 红在 P3 坐标系里根本不在同一个位置,结果偏色。必须从 Figma/Sketch 用 ColorSync 或 Photoshop 导出真实 P3 值。

坑二:非 P3 设备上会静默降级

大多数 Windows 显示器和 Android 老机型上,color(display-p3) 会静默降级到 sRGB 近似值。同样的代码,P3 屏幕看是鲜艳的紫,非 P3 屏幕看是暗淡的紫——不是 bug,是 progressive enhancement。

坑三:Chrome 在 Windows/Linux 上有限支持

截至 2026 年,Chrome 对 color(display-p3) 的 P3 支持仅在 macOS 上完整生效。用 @media (color-gamut: p3) 做条件判断:

.button { background: #8b5cf6; }
@media (color-gamut: p3) {
  .button { background: color(display-p3 0.485 0.256 0.887); }
}

DevTools 验证三步

  1. 在 P3 设备上打开 Chrome/Safari DevTools
  2. 选中使用了 color(display-p3) 的元素
  3. Color picker 里看是否显示「Display P3」标识

三步下一步

  1. 查设计稿:问设计师下次出图时,有没有用 P3 色域导出
  2. 加渐进增强:现有 sRGB 色值上加 @media (color-gamut: p3) 条件升级
  3. 迁移派生逻辑:把 Sass 的 lighten()/darken() 替换为 CSS relative color syntax

一个设计系统和它的代码之间,隔着整个色彩空间。color() 把这个断层从工程问题降级成了配置问题——你只需要问设计师要一对 P3 色值,剩下的交给浏览器。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 13 阅读