scss的saturate()和desaturate()函数操作hsl模型中的饱和度分量,编译期生成确定颜色值,非运行时滤镜;参数为相对增减百分比,不溢出,仅支持合法颜色输入。

SCSS里用saturate()和desaturate()前先搞清它动的是哪个值
这两个函数操作的是 HSL 颜色模型里的 饱和度(saturation)分量,不是 CSS filter: saturate() 那种运行时滤镜。它们在编译期就把颜色算出来,输出的是一个确定的十六进制或 RGB 值,不依赖浏览器渲染时的计算。
这意味着:如果你写 saturate(#888, 30%),Sass 会直接生成一个新颜色(比如 #a1a1a1),而不是给元素加一层动态饱和度调节层。所以它适合做主题色变体、按钮 hover 色、状态色等静态衍生色,不适合做交互动态调色。
- 输入必须是合法颜色值:
#fff、rgb(255,0,0)、hsl(0, 100%, 50%)、甚至已定义的变量如$primary - 不能对非颜色值(如字符串
"red"或未定义变量)使用,否则编译报错:Error: $color: "red" is not a color. - 参数中的百分比是“相对当前饱和度的增减量”,不是目标饱和度值。例如
saturate(hsl(0, 20%, 50%), 50%)是把 20% 饱和度 +50% → 变成 70%,不是设为 50%
为什么saturate($color, 100%)有时没变化?
因为原始颜色可能已经处于最大饱和度——比如纯红 #ff0000 对应 HSL 是 hsl(0, 100%, 50%),再调 saturate(..., 50%) 也还是 100%,Sass 不会溢出。同理,灰阶色如 #888 饱和度为 0%,用 desaturate() 也不会更灰。
常见误判场景:
- 对
rgba(0,0,0,0.5)使用saturate():透明度不影响饱和度计算,但结果仍是半透黑色,视觉上“看不出变化” - 对已用
grayscale()处理过的色再saturate():灰度色饱和度恒为 0%,saturate()无效 - 传入带单位的数值,如
saturate($c, 25px):报错,第二个参数必须是无单位百分比或小数(0.25等价于25%)
saturate() 和 CSS filter: saturate() 别混用
名字一样,但完全两回事:
-
saturate($color, 20%)→ Sass 编译期函数,输出新颜色值,无运行时开销 -
filter: saturate(1.2)→ CSS 运行时滤镜,作用于整个元素渲染结果,支持动画、可响应式调整,但受浏览器兼容性限制(旧版 Safari 对contrast(0)渲染异常) - 混用风险:比如你用
saturate(#f00, 50%)得到一个高饱和红,又在该元素上加filter: saturate(0.5),结果是双重去色,容易过暗或发灰 - 性能提示:大量使用
filter(尤其叠加多个)可能触发额外 GPU 合成,而 Sass 颜色函数零运行时成本
实用组合:用saturate()配合lighten()做可用的 hover 色
单纯调饱和度往往不够——比如对深蓝 #0a3d62 执行 saturate(..., 30%),结果还是太暗,hover 时用户感知弱。更稳妥的做法是同步微调明度:
$base-blue: #0a3d62;
.btn {
background-color: $base-blue;
&:hover {
background-color: saturate(lighten($base-blue, 8%), 12%);
}
}
这样既保留原色倾向(靠 saturate 强化),又提升可读性(靠 lighten 提亮)。注意顺序:lighten 必须在外层,否则先饱和再提亮,可能溢出亮度上限导致失真。
真正容易被忽略的一点:Sass 颜色函数对 HSL 分量的操作是线性的,但人眼对色彩变化是非线性的。所以 saturate($c, 10%) 在浅色上看起来变化小,在中等饱和色上最明显,在深色上可能几乎不可辨——别迷信数值,始终以实际渲染效果为准。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











