Less中直接写filter: grayscale(1)会失效,因编译器不合并多条filter声明且不支持空格拼接变量;须用~""初始化@filter-list,条件追加滤镜字符串,最后通过e(@filter-list)输出无引号的有效值。

为什么直接写 filter: grayscale(1) 在 Less 里会失效
Less 编译器不合并多个 filter 声明,写两行就会覆盖:比如先定义 @blur: blur(2px),再写 filter: @blur; filter: grayscale(1);,最终只留下 grayscale(1)。更糟的是,用变量拼接如 filter: @blur @grayscale; 会直接报错 Expected ')'——Less 不支持这种裸值空格拼接。
必须用 e() + 字符串插值拼出单个 filter 值
核心是把所有滤镜函数拼成一个带空格的字符串,再用 e() 去掉引号,否则浏览器收到的是带双引号的无效值(如 "blur(2px) grayscale(1)")。
-
@filter-list初始设为~""(空字符串但不加引号) - 每个条件分支用
~"@{filter-list} blur(@{blur})"追加,注意空格在引号内 - 最后统一写
filter: e(@filter-list);,e()是关键,不能漏
示例片段:
.gray-mode(@enabled: true, @opacity: 1) {
@filter-list: ~"";
& when (@enabled = true) {
@filter-list: ~"@{filter-list} grayscale(1)";
}
& when (@opacity < 1) {
@filter-list: ~"@{filter-list} opacity(@{opacity})";
}
filter: e(@filter-list);
}
灰度必须作用于 html,且要兜底逃逸元素
只给 body 加 filter 是无效的——fixed、transform、iframe、canvas、video 和内联 SVG 都会脱离父级滤镜作用域。Less 封装时得同步处理这些例外:
立即学习“前端免费学习笔记(深入)”;
- 主规则必须写在
html上:html { .gray-mode(); } - 兜底层用属性选择器补灰:
iframe, video, canvas, svg image { .gray-mode(); } - 防第三方覆盖:用
html :where(*) { filter: inherit !important; }(注意:where()不支持 IE)
生产环境务必加开关 class,别无条件启用
全站灰度会强制 GPU 合成,低端设备可能卡顿;同时破坏颜色对比度,影响 WCAG 可访问性。Less 封装应默认关闭,靠 class 触发:
html:not(.gray-enabled) { filter: none; }<br>html.gray-enabled { .gray-mode(); }
最容易被忽略的是:某些广告 SDK 动态插入的浮层(z-index: 9999)不会自动继承灰度,得用 JS 监听 DOM 变化并 patch 新节点——Less 做不了这事,得配套运行时逻辑。


















