占位符选择器%仅在:extend()中生效,不可嵌套、传参或直接使用,必须顶层独立声明;:extend()合并选择器且不增权重,而mixin重复输出样式;跨文件需先导入定义文件,链式extend在旧版Less中可能失效。

占位符选择器 % 不会输出 CSS,只在被 :extend() 显式调用时才“注入”到目标选择器中——它不是变量,也不是 mixin,不能嵌套、不能传参、不能直接使用。
占位符必须顶层独立声明,否则编译失败
常见错误是把它塞进规则块里,比如写成 .btn-base { %icon-reset { ... } },Less 会直接报错 ParseError: expected '}'。占位符只能出现在最外层作用域,且不能缩进。
- ✅ 正确:
%icon-reset { display: inline-block; font-size: 0; } - ❌ 错误:
.btn { %icon-reset { ... } }(嵌套非法) - ❌ 错误:
%icon-reset { .inner { ... } }(占位符内部不能嵌套规则)
:extend() 是合并选择器,不是复制样式
这是和 mixin 的本质区别:用 :extend(%icon-reset),最终生成的是 .btn-icon::before, .menu-item::after { display: inline-block; ... };而用 mixin 则每个调用处都重复一遍声明。
- 适用场景:跨组件共用的无参基底行为,如伪元素重置、清浮动、文本截断、隐藏辅助文本
- 不适用场景:需要传参(如颜色、尺寸)、局部覆盖某条属性、或需单独调试的样式块
- 注意权重:
.btn:extend(.disabled)会把.disabled的权重(0-1-0)带进来;但:extend(%xxx)不提升权重,因为%本身无权重
跨文件使用时,@import 顺序决定能否识别
% 不是运行时引用,而是编译期文本拼接。如果 @import "mixins.less" 在 @import "buttons.less" 后面,而后者已用 :extend(%reset),就会报错 Undefined reference to '%reset'。
立即学习“前端免费学习笔记(深入)”;
- 必须保证定义
%xxx的文件先被@import,且不能依赖@import (reference)来“隐藏”它——(reference)只抑制 CSS 输出,变量和占位符仍注入全局作用域 - 不要在同一个项目里多个文件都定义同名占位符,最后导入的那个生效,前面的被覆盖
- 大型项目建议统一收口到
placeholders.less,并放在所有组件文件之前导入
链式 extend 在旧版 Less 中可能失效
像 %a:extend(%b) → .x:extend(%a) 这种写法,在 Less 3.0 以下版本(如 2.7.3)中无法穿透解析,.x 最终不会获得 %b 的样式。
- 稳妥做法:只做单层
:extend(%xxx),避免间接继承 - 若真需多级复用,改用 mixin 封装逻辑,或把公共样式抽成原子类(如
.visually-hidden)显式添加 - 检查当前构建环境的 Less 版本:
lessc --version,低于 3.5 建议升级
真正容易被忽略的是:占位符一旦被 extend,就和目标选择器“焊死”在一条 CSS 规则里,后续想单独覆盖其中某条声明(比如只改 font-size),就必须写出同等或更高权重的选择器——它不像 mixin 那样每处都是独立副本,灵活性更低,但体积更小。


















