设计师给你一个 Display P3 色值,旧浏览器根本显示不出来——今天 color() 把这件事彻底原生化了

设计师给你一个颜色,说这是 Display P3 的,要用在 logo 上。你写进 CSS,Chrome 对了,Safari 也对了,但用户的旧 Chrome 显示出来偏了。

以前这个问题的解法是:找工具把 Display P3 转成 sRGB,算出一个近似值写进 CSS。运气好差得不多,运气不好你得配两套。今天 color() 把这件事彻底原生化了——一条 CSS 同时搞定 Display P3 显示和 sRGB fallback。

color() 的基本语法

color() 来自 CSS Color Level 5,允许你直接指定任意颜色空间:

/* 直接写 Display P3 颜色 */
.logo {
  background-color: color(display-p3 1 0.5 0);
}

/* 加透明度 */
.overlay {
  background-color: color(display-p3 1 0.5 0 / 0.8);
}

/* 支持的颜色空间 */
color(srgb 1 0 0);           /* 标准 RGB */
color(display-p3 1 0 0);     /* 苹果主推的广色域 */
color(prophoto-rgb 0.8 0.1 0.05); /* 照片级广色域 */
color(xyz-d65 0.41 0.21 0.09); /* CIE XYZ 绝对色域 */

这解决了第一个问题:设计师给你的 Display P3 值,原样写进 CSS,现代浏览器直接显示正确颜色。

相对颜色语法——从主色自动派生全家桶

真正值钱的在后面。color() 支持相对颜色语法,格式是 color(from <origin> <colorspace> c1 c2 c3 / A)

/* 以 --primary 为起点,输出 sRGB 系的同色系 */
.button {
  --primary: color(display-p3 0.85 0.2 0.35);

  background-color: var(--primary);
  /* 暗色版本 */
  background-color: color(from var(--primary) srgb 0.7 0.1 0.2);
  /* 亮色版本 */
  background-color: color(from var(--primary) srgb 1.2 1.2 1.2);
  /* 加透明 */
  background-color: color(from var(--primary) srgb r g b / 0.5);
}

这里的 rgb 是从原始颜色提取的通道值,可以在输出时重新组合、计算。OKLCH 空间下做明度调整最精准:

:root {
  --brand: oklch(55% 0.2 240);

  /* 浅色变体 */
  --brand-light: color(from var(--brand) oklch calc(l + 30%) c h);
  /* 暗色变体 */
  --brand-dark: color(from var(--brand) oklch calc(l - 20%) c h);
  /* 饱和度加倍 */
  --brand-saturated: color(from var(--brand) oklch l calc(c * 2) h);
}

以前做设计系统色阶:设计师给主色,工程师用工具算出 n 个变体,每次改主色要全部重新算。现在主色改一个值,所有变体自动更新。

自动 fallback——旧浏览器也有得看

color() 的另一个价值在于渐进增强语义:

.card {
  /* 现代浏览器显示 Display P3 广色域 */
  background-color: color(display-p3 0.92 0.45 0.38);
  /* 旧浏览器 fallback——写在前面的普通 sRGB 声明 */
  background-color: #EB7342;
}

旧浏览器不认识 color(),直接忽略,然后用前面的 #EB7342。Chrome 98+ / Safari 15.1+ / Firefox 113+ 支持 color()。主流移动端浏览器全部支持,Safari iOS 15 之后完全覆盖。

完整实战:设计系统色阶自动派生

用一个实际场景把上面的能力串起来。假设设计系统主色是 Display P3,我们需要派生一套完整的色阶:

:root {
  /* 主色——设计师给的 Display P3 值 */
  --color-primary: color(display-p3 0.72 0.15 0.88);

  /* 10 阶明度色阶 */
  --color-50: color(from var(--color-primary) srgb calc(r * 1.1 + 0.1) calc(g * 1.1 + 0.1) calc(b * 1.1 + 0.1));
  --color-100: color(from var(--color-primary) srgb calc(r * 1.05 + 0.05) calc(g * 1.05 + 0.05) calc(b * 1.05 + 0.05));
  --color-500: var(--color-primary);
  --color-900: color(from var(--color-primary) srgb calc(r * 0.6) calc(g * 0.6) calc(b * 0.6));

  /* 语义色:hover / active / disabled */
  --color-primary-hover: color(from var(--color-primary) srgb r g calc(b * 0.8));
  --color-primary-active: color(from var(--color-primary) srgb calc(r * 0.85) calc(g * 0.85) calc(b * 0.85));
  --color-primary-muted: color(from var(--color-primary) srgb r g b / 0.15);

  /* 对应主题变量 */
  --surface-primary: var(--color-primary);
  --text-primary: color(from var(--color-primary) srgb 1 1 1 / calc(1 - l));
}

.btn-primary {
  background-color: var(--surface-primary);
  color: var(--text-primary);
}

.btn-primary:hover {
  background-color: var(--color-primary-hover);
}

改一处主色,整个系统的颜色变体全部自动更新。这是以前 Sass / PostCSS / JS 工具才能做到的事情,现在纯 CSS 原生支持。

下一步:把这三件事用起来

第一,你现在就可以把设计师给的 Display P3 值写进 color(),不需要任何工具。

第二,把设计系统里的颜色变量改成相对颜色语法,主色一变,全部变体自动更新。

第三,如果你的项目还在用旧版浏览器,用 CSS 层叠让 color() 和普通色值共存:新浏览器用广色域,旧浏览器用 sRGB fallback,渐进增强零成本。

color() 是 CSS 颜色系统的补完——从 rgb() hsl() 到 oklch(),再到 color(),终于把「指定颜色空间」这件事原生化了。设计师给你的 P3 色值,不需要转,不需要工具,直接写进去就行。

评论区

0 条评论

登录后可评论。

小鹿·界面实验室 601 阅读