RGB插值必经灰色是因为浏览器在sRGB空间线性插值,R/G/B通道独立计算,导致跨色相过渡(如蓝→红)中间产生灰阶色;oklch()仅作输入语法糖,transition仍转为RGB插值,仅@keyframes动画中全用oklch()才可能启用OKLCH插值。

transition 用 RGB 插值时为什么必经灰色?
浏览器对 background-color 或 color 的过渡,默认在 sRGB 空间做线性插值——也就是把起始色和结束色的 R、G、B 三个通道各自独立拉直线。人眼对色相(H)和饱和度(S)的变化敏感,但 sRGB 不是感知均匀空间,所以从蓝色 rgb(0,0,255) 到红色 rgb(255,0,0) 的中间点会是 rgb(128,0,128)(紫灰),再往中间走就越来越灰。这不是 bug,是数学必然。
oklch() 写进去就能在 OKLCH 空间过渡吗?
不能。仅把颜色值写成 oklch() 并不会改变插值空间:
-
transition仍强制转回 RGB 插值,oklch()只是“输入语法糖” - 真正启用 OKLCH 插值,目前只支持在
@keyframes动画中,且所有关键帧必须统一使用oklch()(或全用lch()),Chrome 112+、Safari 16.4+ 才认 - 例如:
@keyframes fade { from { background-color: oklch(0.6 0.2 270); } to { background-color: oklch(0.6 0.2 0); } }这样才可能走 OKLCH 路径
那怎么让 transition 看起来不灰?
绕过底层限制,靠控制路径和节奏来骗过眼睛:
- 用
color-mix(in oklch, ...)配合自定义属性生成中间色阶,再用steps()做离散跳变:比如transition: background-color 0.4s steps(12, end) - 改用 HSL 定义起止色,并手动加一两个中间停靠点(如
hsl(240,100%,20%) → hsl(300,80%,40%) → hsl(0,100%,80%)),比纯两端 RGB 更可控 - 调
transition-timing-function:默认ease在中间段加速太猛,容易暴露灰阶;换成cubic-bezier(0.4, 0.1, 0.3, 1)能压平中段速度,让灰阶停留时间变短 - 禁用
opacity模拟过渡——它会让所有通道同步衰减,叠加背景后更容易显灰
OKLCH 真正该用在哪?
不是用来修 transition,而是用来定义和管理颜色本身:
立即学习“前端免费学习笔记(深入)”;
- 品牌主色用
oklch(0.62 0.28 258.5)定义,禁用态只降C(如0.12),深色模式只调L(如0.38),避免意外偏色 - 配色系统生成:固定
H和C,批量调节L得到明暗阶梯,比手调hsl()的L更稳定 - 务必带
rgb()回退:老浏览器不识别oklch()会跳过整条声明,按钮直接透明
插值空间这事,浏览器还没放开给 transition;现在能做的,是让颜色本身更“干净”,再用 timing 和混合技巧避开灰区。


















