CSS颜色函数和色彩管理。

不能说的秘密
不能说的秘密 星耀SVIP星耀SVIP
发布于 2026-08-02 21:57 ·70 浏览 ·0 回复

写现代 CSS 配色的最短路径是:调色板用 oklch() 定义,交互态用 color-mix() 派生,面向广色域屏幕用 color(display-p3 …) 增强,同时给老浏览器留一条 rgb()/hsl() 回退。结论:颜色函数不是语法糖的堆砌,而是决定你的主题在一台千元手机和一台广色域笔记本上会不会同时翻车的基础设施。

三组函数,各管一段

结论:rgb()/hsl()/hwb() 是 sRGB 时代的工具,lab()/lch()/oklab()/oklch() 是感知均匀的现代色彩空间,color() 用来显式声明色域。

rgb() 和 hsl() 都工作在 sRGB 色域内,其中 HSL 的 L 并不等于人眼感知亮度——hsl(60 100% 50%) 的黄色看起来比同样 L 值的蓝色亮得多,这正是用 HSL 做色板容易「深浅不齐」的根本原因。

oklch(L C H) 由 OKLab 转成圆柱坐标:L 是感知亮度(0–1 或 0%–100%),C 是彩度,H 是色相角度。OKLab 是 Björn Ottosson 提出的色彩空间,设计目标就是让数值距离尽量接近人眼感知差异。

color(display-p3 1 0 0) 则可以显式指定输出色域。另外现代语法统一为空格分隔、/ 后接透明度,例如 rgb(0 0 0 / 50%)、oklch(0.7 0.15 250 / 0.6);rgba()、hsla() 仍可用,但没有必要再写。

用 OKLCH 搭色板的正确姿势

结论:同一套色板应固定 L 和 C,只旋转 H,这样所有主色看起来「一样亮」。

:root{
  --brand-h: 250;
  --brand:       oklch(0.62 0.17 var(--brand-h));
  --brand-hover: oklch(0.56 0.17 var(--brand-h));
  --brand-soft:  oklch(0.94 0.04 var(--brand-h));
}

三个要点:hover 态只改 L(0.62→0.56),改 H 就变成另一种颜色了;浅底色把 C 压到 0.05 以下,否则容易灰得发脏;正文字色 L 建议不高于 0.5,保证对比度达标。

注意:OKLCH 有实际边界,某个 L/H 下 C 写得太大会超出 sRGB 范围,浏览器会自动做 gamut mapping(色域映射)。所以别把 C 盲目堆到 0.4,色相越亮的地方可用的最大 C 越小。

color-mix() 与相对颜色:主题变量该这么派生

结论:能用 color-mix() 算出来的颜色就别手写十六进制,换主色时一处生效、全站跟随。

.card{ background: color-mix(in oklab, var(--brand) 12%, white); }
.btn:hover{ background: color-mix(in oklab, var(--brand) 85%, black); }
.border{ border-color: color-mix(in srgb, var(--brand), transparent 70%); }

in oklab 指定插值空间:和白色、黑色混建议用 oklab,得到的中间色不会发灰;和 transparent 混用 srgb 更符合直觉,因为预设空间下的 alpha 插值是线性的。相对颜色语法则可以只改某个通道:

:root{ --brand-dark: oklch(from var(--brand) calc(l - 0.08) c h); }

色彩管理:sRGB、P3 与色域声明

结论:sRGB 是默认色域,P3 是当下手机和笔记本更广的色域;不显式声明,浏览器一律按 sRGB 解释你的颜色。

具体来说:十六进制和 rgb()/hsl() 全部按 sRGB 处理;要输出广色域就写 color(display-p3 r g b),分量取 0–1;用 @media (color-gamut: p3) 检测设备能力后再做增强,而不是直接替换。

一个常被忽略的点是:OKLCH 里那些超出 sRGB 的高彩度颜色,在 sRGB 屏幕上必须被映射到可显示范围内,映射结果由浏览器的色域映射算法决定,你不一定能精确预测。所以「用 OKLCH 写色板」和使用者是 sRGB 还是 P3 屏幕,是两件需要分别处理的事。

降级写法与两个常见坑

结论:新颜色语法是增量增强——先写一行 sRGB 回退,再写新语法,不支持的浏览器自动忽略后者。

.btn{
  background: #4f46e5;               /* 回退 */
  background: var(--brand);          /* 增强 */
}
@supports (color: oklch(0 0 0)) { /* … */ }

坑一:把 oklch() 存进 CSS 变量再使用,回退会失效——变量赋值在不支持的浏览器里照样「解析通过」,直到真正被使用才报错。稳妥做法是变量里存新语法,同时在用它的地方先给一个纯 sRGB 字面值。

坑二:别忘了几个非颜色函数但同属色彩管理的属性——currentColor 让边框和图标跟随文字色;color-scheme: light dark 让表单控件跟随系统深色模式;light-dark() 可按 color-scheme 直接给出两个值。

收束一下:色板用 OKLCH 定,交互态交给 color-mix() 和相对颜色语法派生,广色域用 color(display-p3 …) 加 @media (color-gamut: p3) 做增强,降级靠「先字面值、后新语法」的叠加写法。把这四步固定下来,配色就从「调到手酸」变成一套可维护的规则。

本文转载自 Clara轻量论坛系统,原文地址:https://www.leleweb.cn/thread-415.html
转载请注明出处,版权归原作者所有。
他们都看过 1 人浏览过
CLARA轻量论坛系统

全部回复 0

还没有回复,来抢沙发~