Detach ruleset 是未求值的样式容器,需显式展开(如+@ruleset)才生效;不自动渲染、不支持参数、变量作用域绑定定义处,误用会导致样式消失。

Detach ruleset 不是用来“优化性能”的,而是用来组织和复用复杂样式逻辑的——它本身不减少 CSS 体积或加快编译速度,但能显著降低维护成本、避免重复定义、提升条件样式的可读性。
为什么 detach ruleset 常被误用为 mixin
很多人写完 @btn-base: { padding: 0.5em 1em; } 就以为样式生效了,结果浏览器里完全没渲染。这是因为 detach ruleset 是“未求值的容器”,不是函数也不是 mixin:
• 它不会自动展开进输出 CSS
• 它不接受参数(不像 .mixin(@a) { ... })
• 它内部变量只捕获定义时的作用域,不能动态读取调用处的 @color 等变量
• 忘记加 + 展开,是样式消失最常见原因
把 ruleset 当作 mixin 参数传入并展开
这是最实用的场景:把基础样式抽成 ruleset,再由不同状态 mixin 控制如何叠加。关键点在于参数类型声明和展开方式:
• Less 4.0+ 要求 mixin 参数显式标注为 @ruleset 类型
• 必须用 +@param 展开,@param() 在嵌套中可能静默失败
• ruleset 内部若需调用方变量,得提前插值,比如 color: @{color};
.button-variant(@color, @ruleset) {
background-color: @color;
+@ruleset; // 这里必须加 +
}
@btn-base: {
display: inline-flex;
align-items: center;
font-size: 1rem;
};
.primary-btn {
.button-variant(#007bff, @btn-base);
}
用多个 ruleset 拼接状态样式(如 disabled + loading)
比起写一堆带条件判断的 mixin,用 ruleset 组合更直观,也更容易测试和复用:
• 多个 ruleset 需逐个 + 展开,没有“合并”操作符
• 同名属性按展开顺序覆盖(后展开的胜出),符合 CSS 层叠直觉
• 注意 & 嵌套行为:ruleset 中的 &:disabled 会展开到当前选择器上下文,不是全局;但若在 ruleset 里写 .disabled(无 &),就会污染全局命名空间
• 不支持在 @media 或 :hover 块内直接定义 ruleset 并期望继承父作用域变量——它只记住定义那一刻的变量快照
立即学习“前端免费学习笔记(深入)”;
容易被忽略的边界问题
ruleset 的延迟求值特性带来灵活性,也埋下几个隐蔽坑:
• 变量作用域捕获是“定义时”而非“调用时”,@text-color 在 ruleset 外修改,不影响已定义的 ruleset
• 无法在 @keyframes 或 @font-face 中直接使用 ruleset
• extend() 和 merge 对 ruleset 无效,别试图用它们做样式合并
• 编译错误提示常指向 ruleset 定义行,而不是实际调用位置,排查时要逆向追踪作用域链


















