lch()可精准变暗,color-mix()因线性混色导致明度不统一;应以lch()定义主色并动态调整l值,配合clamp()和@supports fallback确保兼容与设计一致性。

不能“一键生成”,但可以用 lch() 或 lab() 做语义化变暗,接近“一键”效果;color-mix() 不适合——它线性混合,不是按明度变暗。
为什么 color-mix() 不能当阴影生成器用
很多人看到 color-mix(in srgb, #007bff 70%, black 30%) 就以为能“自动压暗主色做阴影”,结果发现:蓝色发灰、红色偏棕、绿色变浊。这是因为 color-mix() 在 srgb 空间里做的是线性插值,不理解“变暗”在人眼感知中是降低明度(L),而不是简单混黑。不同色相下,混入同样比例黑色,L 值下降幅度差异很大,视觉不统一。
常见错误现象:
- 卡片换主题色后,阴影突然显得过重或过淡
- 深色模式下,原
color-mix()阴影在暗背景上发亮刺眼 - 设计系统里同一套 mix 规则,在红/蓝/黄主色上阴影深度不一致
用 lch() 精控明度才是正解
lch() 把颜色拆成 L(明度,0–100)、C(彩度)、H(色相),改 L 就是真·变暗,不扰动颜色本质。比如主色是 lch(60% 70 240),阴影直接写 lch(35% 70 240),色相和彩度全保留,只降 25 点明度,视觉上就是“同一个颜色更沉一点”。
实操要点:
- 主色必须用
lch()或lab()定义,别拿rgb()主色去套lch()阴影——色彩空间不匹配,结果不可控 -
L值建议降 15–25,降太多(如L: 10)会失去层次,尤其在深色 UI 中容易糊成一片 - 务必用
clamp(0, calc(...), 100)包一层,防止计算出负L或超 100 导致整个声明失效 - 浏览器支持:Chrome 111+、Safari 16.4+、Firefox 117+;旧版必须 fallback 到预计算的
rgba()
怎么写才真正“一键”可维护
别在每个 box-shadow 里硬写 lch() 值。把明度偏移逻辑抽到自定义属性里,配合 calc() 动态算:
:root {
--primary-lch: lch(60% 70 240);
--shadow-l: clamp(20, calc(60 - 25), 55); /* L 基准值来自主色,-25 是固定压暗量 */
}
.card {
background: var(--primary-lch);
box-shadow: 0 2px 8px lch(var(--shadow-l) 70 240);
}
这样换主题色时,只需改 --primary-lch 和对应 --shadow-l 的基准值,所有阴影自动同步。注意:box-shadow 里不能用 hsl() 混搭 lch(),上面示例中 hsl() 仅作 fallback 占位,真用必须全链路用 lch()。
fallback 不是可选,是必填项
CSS 里没法用 JS 实时把 lch() 转成 rgb()。要兼容老浏览器,必须提前算好。推荐做法:
- 用在线工具(如 https://bottosson.github.io/misc/colorpicker/)输入目标
lch(35% 70 240),复制生成的十六进制值(如#1a3d8c) - 转成
rgba():用取色器查该色在 sRGB 下的 alpha 推荐值,通常rgba(26, 61, 140, 0.3)比直接rgba(26, 61, 140, 1)更自然 - 用
@supports隔离新旧语法:@supports (box-shadow: 0 0 0 lch(0% 0 0)) { ... },里面写lch()版本;外面写rgba()fallback
最容易被忽略的一点:深色模式下,你写的 lch(35% ...) 阴影在暗背景上可能依然太亮——这不是语法问题,是设计决策缺失。得额外定义一套深色模式变量,比如 --shadow-l-dark: clamp(40, calc(60 - 10), 70),否则所谓“自动”就只是伪命题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











