darken() 和 lighten() 实际是直接增减 HSL 的 L 值,非线性变暗/亮;对纯黑/白无效;推荐用 adjust-color() 精确控制;CSS 变量中避免硬编码其结果;需人工校验 WCAG 对比度。

darken() 和 lighten() 的实际效果不是“变暗/变亮”,而是调整 HSL 中的亮度值
很多人以为 darken($color, 10%) 就是把颜色“压暗 10%”,其实它是在当前颜色的 HSL 表示中,**直接减去 10% 的 L(Lightness)值**。比如 hsl(200, 50%, 70%) 经过 darken(..., 20%) 变成 hsl(200, 50%, 50%),而不是按 RGB 线性插值。这意味着:
- 对浅色(L 接近 100%)调用 darken() 效果明显,但对深色(L 接近 0%)可能几乎无变化;
- 对纯黑 #000 使用 darken() 完全无效(L 已为 0%,无法再减);
- 同样,lighten(#fff, 10%) 也毫无反应。
别直接用 darken()/lighten() 做主题色推导,优先考虑 adjust-color()
如果你需要一套语义化、可预测的配色(比如主色、强调色、禁用态),darken() 和 lighten() 容易失控。更稳妥的是用 adjust-color(),它支持同时调 H/S/L,且能指定绝对值而非相对百分比:
$primary: #4a6fa5; $primary-light: adjust-color($primary, $lightness: 20%); $primary-dark: adjust-color($primary, $lightness: -15%);
这样比 lighten($primary, 20%) 更可靠——后者在某些起始亮度下可能溢出(如 L=85% + 20% → 105%,Sass 会截断为 100%,导致意外变白)。
在响应式或模式切换中,避免在 CSS 变量里硬编码 darken/lighten 结果
Sass 编译时就固定了颜色值,所以你不能指望 --primary-dark: #{darken($primary, 15%)} 在运行时随用户系统主题动态变化。如果要做深色模式适配:
- 不要用 Sass 函数生成两套变量再靠媒体查询切换;
- 改用 CSS 原生 color-scheme + prefers-color-scheme 配合自定义属性;
- 或者把基础色存为 HSL 变量(如 --h: 210; --s: 40%; --l: 55%),再用 hsl(var(--h), var(--s), calc(var(--l) - 10%)) 实现运行时明暗调节。
lighten() 在浅灰背景上容易导致对比度不足,必须人工校验 WCAG
比如从 #f0f0f0 调用 lighten($color, 5%) 得到 #f5f5f5,和白色文字搭配时对比度可能低于 4.5:1(AA 标准)。Sass 不会警告你这点。建议:
- 所有用于文本/边框的颜色推导后,用浏览器 DevTools 的无障碍面板检查对比度;
- 把关键色阶(如 $text-primary, $text-secondary)单独定义,不依赖函数链式生成;
- 第三方工具如 contrast-ratio npm 包可在构建时做自动化校验。
真正难的不是写出 darken(),而是判断什么时候不该用它——尤其是当设计系统开始要求可访问性、跨模式一致性、以及开发可维护性的时候。


















