oklab 本身不能减少渐变灰暗问题,因浏览器对 linear-gradient() 的插值始终在 srgb 空间进行;真正有效的是手动控制 oklab 插值路径,通过采样转 rgb() 停靠点实现视觉均匀过渡。

OKLab 本身不能减少渐变灰暗问题——浏览器对 linear-gradient() 的插值始终在 sRGB 空间进行,无论你用 oklab()、oklch() 还是 hsl() 写端点,中间色都是 RGB 算出来的。
真正起作用的,是你用 OKLab 思路**手动控制插值路径**。下面说清楚怎么做、为什么、以及最容易栽跟头的地方。
为什么 linear-gradient(in oklab, ...) 会静默失效
所有主流浏览器(Chrome 124+、Firefox 125、Safari 17.5)都不支持 in oklab 语法。写成:linear-gradient(in oklab, oklab(0.5 -0.12 0.08), oklab(0.7 0.15 0.2))
会被解析器直接跳过,整条声明丢弃,不报错、不 fallback、背景可能变透明或回退到上一条规则。
这不是兼容性问题,是规范未纳入——CSS 渐变目前强制 sRGB 插值,in oklab、in lch、in oklch 全部无效(SVG 的 <lineargradient></lineargradient> 标签除外)。
用 color-mix(in oklab, ...) 做单点混合可行但有硬限制
color-mix() 是当前唯一能在纯 CSS 中触发 OKLab 插值的函数,但它只输出一个静态颜色,不是渐变:
- 必须两端都用
oklab()或oklch(),混用#rrggbb或rgb()会让整条声明失效 - 浏览器支持有限:Chrome 112+ 和 Safari 17.5+ 支持,Firefox 尚未实现
- 写法必须严格:
color-mix(in oklab, oklab(0.5 -0.12 0.08) 60%, oklab(0.7 0.15 0.2) 40%)—— 百分比总和必须为 100%,且不能省略空格 - 它无法替代渐变;想模拟多段过渡,得手写多个
color-mix()配合 CSS 变量,或交给 PostCSS 插件生成
最可靠方案:用 OKLab 工具采样 + 手写 RGB 停靠点
这是目前落地最稳、兼容性最好、效果最可控的做法。核心是:用 OKLab 色空间算出视觉均匀的中间色,再转成 rgb() 输出给浏览器插值。
- 用 Björn’s OKLCH Picker 或
culori库,在起点和终点之间采样 5–7 个 OKLAB 均匀步进点 - 导出每个点对应的
rgb()值(别用oklch()直接输出,Safari 对它的插值行为未标准化) - 停靠点间隔 ≤20%,例如:
rgb(230, 225, 220) 0%, rgb(210, 205, 215) 20%, rgb(180, 175, 205) 40%……避免浏览器在大跨度内做长距离 RGB 插值 - 色相差 >180° 时必须手动拆段,比如从
oklch(0.7 0.25 350)到oklch(0.7 0.25 10),要写成三段:oklch(0.7 0.25 350), oklch(0.7 0.25 0), oklch(0.7 0.25 10),否则浏览器按 340° 差值走远路,中间必然发灰
容易被忽略的细节:alpha 和设备渲染差异
很多人加了停靠点还是灰,问题常出在这几个地方:
-
rgba()渐变在 Safari 中尤其危险:它会对 R/G/B/A 四通道分别线性插值,叠加在白色背景上,中间段极易泛白灰。纯色过渡优先用rgb()+ 背景色控制,透明需求改用background-blend-mode或遮罩层 - 移动端 iOS Safari 对浅色过渡(如
#fff9cc → #ffffff)极度敏感,哪怕无 alpha,也建议加 1–2 个中间停靠点 - 导出的
rgb()值务必在真机(尤其是 MacBook LCD 屏)上验证 banding 是否缓解——工具算得再准,硬件色深(6bit vs 8bit)和 gamma 曲线才是最终呈现者
rgb() 和百分比。任何指望“写个 in oklab 就自动变好”的尝试,都会卡在解析阶段。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











