oklch可解决深色模式阴影发灰问题,因其l值感知均匀,需严格按oklch(l% c h)格式书写(l带%、c为小数、h无单位),配合@supports(color: oklch(0% 0 0))检测并前置rgba()降级。

深色模式下阴影发灰,不是模糊值问题,是颜色空间选错了
直接用 rgba(0, 0, 0, 0.3) 或 hsl(0, 0%, 0%, 0.3) 给阴影设色,在暗背景上会显脏、失层次——因为 sRGB 和 HSL 的亮度通道不感知均匀,0.3 的 alpha 叠加在深色底上,实际明暗跳变远超人眼舒适区。OKLCH 的 L 才真正对应人眼对阴影“深浅”的判断,必须用它调亮度,而不是靠透明度“压暗”。
用 oklch() 写阴影色的三个硬规则
浏览器解析 oklch() 极其严格,错一个字符就整条声明失效(尤其 Safari 16.x–17.3):
-
L必须带单位:oklch(25% 0.15 240)✅,oklch(0.25 0.15 240)❌(旧 Safari 不认小数写法) -
C(色度)要压低:深色阴影不是“纯黑”,而是带微弱蓝/灰倾向的低饱和色,C: 0.08–0.18比0更自然;C过高(如0.3)会让阴影泛紫或发青 - 别混空间:
box-shadow: 0 4px 12px oklch(25% 0.12 240), 0 0 0 rgba(0,0,0,0.1)→ 后者会破坏 OKLCH 插值,动画时颜色跳变;所有节点必须统一用oklch()
如何为不同层级卡片配 OKLCH 阴影
关键不是改模糊半径,而是按视觉深度同步调整 L 值——离用户越近的元素,阴影 L 越高(更亮),但始终低于背景色的 L:
- 浮层/弹窗:
oklch(35% 0.1 240)(比深灰背景oklch(20% 0 0)亮 15%,有明确抬升感) - 主卡片:
oklch(28% 0.12 240)(中等对比,不抢内容) - 按钮悬停:
oklch(32% 0.09 240)(微提亮度+略降色度,避免刺眼) - 禁用态阴影:
oklch(22% 0.05 240)(不消失,但明显收敛)
注意:所有值都基于同一色相 H: 240(蓝调),换红/绿系需重新校准 C 上限——OKLCH 下蓝的 C=0.18 很稳,但红到 C=0.12 就可能发棕。
@supports 检测和降级必须这么写
不能把 fallback 放在 @supports 块里,否则旧浏览器直接跳过整个规则:
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
@supports (color: oklch(0% 0 0)) {
box-shadow: 0 4px 12px oklch(28% 0.12 240);
}
重点:
- 检测只用
@supports (color: oklch(0% 0 0)),别用oklab()或not否定式(安卓 WebView 解析失败) - 降级色必须写在
@supports外,且用rgba()而非hsl()——后者在深色背景下对比度崩得更狠 - 别指望
filter: brightness()补救:它作用于整个元素,会把文字也压暗,且破坏 OKLCH 的感知一致性
最易被忽略的是:OKLCH 阴影在高对比度模式(HC)下会被系统强制清空,这时得靠 @media (forced-colors: active) 加边框兜底,不能只依赖颜色本身表达层级。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











