oklab不能直接用于mask-image渐变,因浏览器强制srgb插值且不支持in oklab语法;可行方案是用color-mix(in oklab)预生成rgb停靠点,再拼入带百分比的linear-gradient()作为遮罩源。

OKLAB 不能直接用于 mask-image 渐变,浏览器不支持在遮罩中解析 OKLAB 空间插值;真正可行的是用 color-mix(in oklab) 预生成中间色,再拼进多段 linear-gradient() 作为遮罩源。
为什么 mask-image: linear-gradient(in oklab, ...) 完全无效
所有主流浏览器(Chrome 124+、Firefox 125、Safari 17.5)对 mask-image 中的渐变,底层强制使用 sRGB 插值。即使你写 linear-gradient(to right, oklab(0.4 0.1 -0.05), oklab(0.85 0.02 0.12)),浏览器也会先转成 RGB,再在 RGB 通道上拉直线——结果就是遮罩边缘发灰、过渡生硬。这不是语法错,是规范层面不支持。
更隐蔽的问题是:Safari 对 transparent 在遮罩中解析极不稳定,常静默转为 #000,导致本该半透的区域直接被裁掉。
-
in oklab写在linear-gradient()里会被完全忽略,不是警告,是静默跳过 - 遮罩渐变只认灰度语义:
#fff= 完全显示,#000= 完全隐藏,中间灰阶 = 半透;oklab()值无法参与这个灰度映射 - Firefox 目前仍不支持
mask-image的任何渐变值,声明直接失效
用 color-mix(in oklab) 手动构造感知均匀的遮罩渐变
color-mix() 是目前唯一能在纯 CSS 中触发 OKLAB 插值的函数,它不依赖运行时渐变引擎,而是静态混合两个颜色,输出一个确定的 RGB 值。你可以用它生成 3–5 个关键停靠点,再喂给 mask-image: linear-gradient()。
例如,要实现从左到右的平滑淡出遮罩,起止色为 oklab(0.9 0.01 0.02)(近白)和 oklab(0.2 0.01 0.02)(近黑),可这样生成中间色:
color-mix(in oklab, oklab(0.9 0.01 0.02) 80%, oklab(0.2 0.01 0.02) 20%); /* 第一停靠点 */ color-mix(in oklab, oklab(0.9 0.01 0.02) 50%, oklab(0.2 0.01 0.02) 50%); /* 中点 */ color-mix(in oklab, oklab(0.9 0.01 0.02) 20%, oklab(0.2 0.01 0.02) 80%); /* 第二停靠点 */
- 必须确保两个输入色都用
oklab()或oklch()格式,混用#rrggbb或rgb()会导致整条color-mix()失效 - Chrome 112+ / Safari 17.5+ 支持,Firefox 尚未实现,需用 JS fallback 或降级为 sRGB 混合
- 生成的每个色值都要手动转成
rgb(),再塞进linear-gradient()的 stop 列表里
构建多停靠点 mask-image 渐变的关键参数
把 color-mix() 输出的多个 RGB 停靠点拼成带百分比的 linear-gradient(),才能避免浏览器在两点之间做长距离 sRGB 插值。停靠点太稀疏,灰带照出;太密,CSS 体积膨胀且无收益。
- 停靠点间隔建议 ≤15%,例如:
linear-gradient(to right, #fff 0%, #f0f0f0 15%, #c0c0c0 30%, #606060 45%, #000 60%) - 必须显式设
mask-size: 100% 100%,否则默认缩放会扭曲渐变比例 -
mask-repeat: no-repeat不可省略,否则渐变会在遮罩区域平铺,边缘出现重复黑边 - Safari 要求
-webkit-mask-image前缀,且不能和mask简写混用——mask: url() 100% 100% no-repeat会重置所有子属性,导致渐变丢失
兼容性兜底与 SVG 替代方案
当 color-mix() 不可用(如 Firefox 或旧 Chrome),或需要更高精度控制(比如波浪形遮罩边缘),SVG 是唯一跨浏览器稳定的方案。它绕过所有 CSS 渐变解析逻辑,直接按 alpha 通道渲染。
内联 SVG 遮罩示例(data URI):
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cmask id='m' maskUnits='userSpaceOnUse' width='100' height='100'%3E%3Crect width='100' height='100' fill='%23fff'/%3E%3Cpath d='M0,50 Q25,30 50,50 T100,50' fill='%23000'/%3E%3C/mask%3E%3C/svg%3E#m");
- SVG 中
fill="%23fff"区域显示,fill="%23000"区域隐藏;路径用贝塞尔曲线定义柔和边缘 - 必须 URL 编码,空格、括号、引号都要转义,否则 Safari 会加载失败
- 用
mask-size: contain配合mask-position: center控制缩放与对齐,避免拉伸变形
复杂点在于:OKLAB 的“自然”是人眼感知维度,而遮罩最终输出仍是 RGB 像素。你无法让浏览器在 mask 渲染时切换色彩空间——能做的只有提前算好感知均匀的灰阶序列,再把它喂进去。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











