灰阶带源于srgb线性插值必然经过视觉灰区,需用color-mix(in lch,)配合显式中间色阶、lch()起止色、拆分background属性及兜底检测来规避,混入任何srgb语法即失效。

这是因为浏览器在 sRGB 色彩空间里对 RGB 通道做线性插值,而互补色(如 #ff0000 和 #00ffff)在 sRGB 坐标系中连线必然穿过低亮度、低饱和度的视觉灰区——不是颜色选得不对,是插值路径本身“走错了路”。
linear-gradient() 的插值永远在 sRGB 空间进行
无论你用 hsl()、lch() 还是 oklch() 写起止色,浏览器最终都会把它们转成 RGB 像素值,再在 RGB 三个通道上分别做等距线性计算。比如从红色 rgb(255, 0, 0) 到青色 rgb(0, 255, 255),中间点就是 rgb(127.5, 127.5, 127.5),即视觉上浑浊的中性灰。
这种灰不是“不够饱和”,而是人眼对 sRGB 插值路径的明度响应严重塌陷所致——它在 LAB 感知空间里根本不是一条直线,而是一条下凹的弧线。
color-mix(in lch, ...) 是目前唯一能绕过该问题的纯 CSS 方案
color-mix() 是少数真正支持指定色彩空间插值的函数,但必须满足几个硬性条件才能生效:
- 两端颜色必须都用
lch()或oklch()表示,混入任意一个rgb()或hsl()就会退回到 sRGB 插值 - 每个
color-mix()必须独立出现在渐变停靠点列表中,不能赋值给 CSS 变量再引用 - 必须显式插入至少两个中间色阶,例如:
linear-gradient(to right, lch(50% 80 20), color-mix(in lch, lch(50% 80 20) 60%, lch(50% 80 200) 40%), color-mix(in lch, lch(50% 80 20) 40%, lch(50% 80 200) 60%), lch(50% 80 200)) - 不能和
background-blend-mode、rgba()、background简写混用,否则整个链路静默降级
停靠点密度比色彩空间选择更关键
即使用了 lch() 起止色,如果只写两段:lch(30% 90 120), lch(70% 90 300),浏览器仍会在两点间做长距离 RGB 插值,灰带照出。真正起作用的是人为压缩插值跨度:
- 停靠点间隔建议 ≤ 20%,例如
0%, 20%, 40%, 60%, 80%, 100% - 优先用工具(如 Björn’s OKLCH Picker)导出等距 OKLAB 步进点,再转成
rgb()值手动写死 - 避免依赖
oklch()直接参与渐变——Safari 对它的插值行为尚未标准化,Chrome 124+ 虽支持但不保证过渡均匀 - 低色深屏幕(如多数笔记本 LCD)上 banding 是硬件限制,加噪点或改用 SVG 渐变可缓解,但无法根除
最易被忽略的一点:alpha 通道永远独立线性插值。哪怕你用 oklch(50% 90 120 / 0.8),透明度变化仍是生硬的——这点必须单独调,不能指望色彩空间一并解决。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











