最可靠做法是用 color-mix(in srgb, var(--base) 90%, black 10%) 加深,而非 hsl(from ...) 直接减 l 值;因后者在深色下易归零失真、人眼感知不均,且无法保证对比度达标。

直接用 hsl(from ...) 调整 l 值最可靠,但“加深10%”不是简单减10——它必须是相对当前亮度的绝对差值,且需防越界。
为什么不能写 hsl(from var(--base) h s calc(l - 10))?
语法上合法,但行为不可控:若基色是 #fff(l = 100),calc(l - 10) 得 90,看起来合理;但若基色是 #111(l ≈ 6.7),结果变成负数,浏览器会截断为 0,导致意外全黑。更糟的是,人眼对暗色微小亮度变化极敏感,-10 在深色区感知远强于浅色区。
常见错误现象:
- 深色按钮悬停后突然“死黑”,失去层次
- 同一段 CSS 应用于不同主题色时,有的变灰、有的溢出、有的几乎无变化
正确做法:用 color-mix() 混合黑色,而非硬调 L 值
color-mix() 是 CSS Color Level 5 中更符合视觉直觉的方式——它模拟颜料混合,对深色、浅色、饱和色都保持一致性。加深本质是向黑色靠拢,不是机械降亮度。
实操建议:
- 写法:
color-mix(in srgb, var(--base) 90%, black 10%)表示“90% 基色 + 10% 黑”,即视觉上“加深约 10%” - 若需更精确控制(如 WCAG 对比度要求),把
10%换成15%或20%,线性可预测 - 不依赖 HSL 转换,避免深色区 L 值归零失真;也不触发 Sass/Less 编译时的亮度溢出报错
兼容性兜底:当 color-mix() 不可用时,用 hsl() + JS 校验
目前 Chrome 111+、Safari 16.4+、Firefox 119+ 支持 color-mix();旧环境需降级。纯 CSS 无法判断当前 l 值是否安全,所以:
- 降级方案优先用
hsl(from var(--base) h s max(0, l - 8))(减 8 而非 10,留缓冲) - 关键组件(如禁用态文字)应在 JS 中读取
getComputedStyle后校验对比度,不信任 CSS 自动计算 - 切勿在 :root 中大量预定义
--base-darker变量——相对颜色语法本意就是实时计算,硬编码反而失去响应性
真正麻烦的不是写法,而是“加深10%”这个需求本身模糊:它是面向设计稿的视觉反馈,还是面向可访问性的对比度达标?前者用 color-mix(),后者必须走 contrast() 函数或外部校验工具。别让一个百分比数字掩盖了实际目标。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











