:extend 是 Less 中通过合并选择器实现样式复用的机制,编译后多选择器共享同一规则,适用于无参、纯样式复用;需动态传参或含嵌套结构时应使用 mixin。

:extend 是 Less 实现真正 CSS 选择器复用的核心机制,它不是复制样式块,而是合并选择器——编译后只保留一份声明,多个选择器共用同一组规则。这和 .mixin() 的“拷贝粘贴”有本质区别,是减少冗余的首选手段。
什么时候该用 :extend 而不是 .mixin()
关键看输出目标:你要的是「多选器共享同一条 CSS 规则」,而不是「每个调用处都生成一份副本」。
- 如果重复的是定位、过渡、基础边框等纯样式声明(如
position: absolute; left: 50%; transform: translate(-50%, -50%)),:extend更合适——编译后.center, .modal, .tooltip共享同一行规则 - 如果需要动态传参(比如不同颜色、尺寸、延迟时间),必须用
.mixin(),:extend不支持参数 - 如果样式中含嵌套结构(如
&:hover或&::before),:extend可继承整个嵌套链,但需注意匹配精度(见下条) - 混合宏在调试时更直观(CSS 文件里能看到每处展开),而
:extend编译后选择器被合并,原始调用痕迹消失,不利于快速定位来源
:extend 的匹配行为和常见翻车点
:extend 匹配的是最终编译出的 CSS 选择器字符串,不是 Less 源码结构。这意味着:
- 选择器必须完全一致才能命中:
.btn无法匹配.btn.primary,除非加all关键字 -
.a:extend(.b)只匹配独立出现的.b;而.a:extend(.b all)会匹配所有含.b的组合,比如.x.b、.b.y、#wrap .b - 嵌套写法中,
&:extend(.base)等价于把:extend写在当前选择器末尾,但容易误写成&:extend(.base) { ... }—— 这会导致语法错误,因为:extend必须紧跟选择器,不能放在规则体里 - 伪类/伪元素不参与继承匹配:
.link:extend(.base)不会自动带上.link:hover,除非.base:hover显式定义且被all捕获
实际项目中怎么组织可继承的基类
不要把所有通用样式塞进一个 .util 类里。按语义分层更可控:
- 用带前缀的占位符类名(如
%flex-center、%sr-only)明确表示“仅用于继承”,避免意外被 HTML 直接引用 - 把视觉无关的抽象规则(如清内外边距、BFC 触发、文本截断)单独抽为基类,例如:
%reset-margin、%overflow-hidden - 对复合行为(如弹窗居中 + 背景遮罩),拆成原子级继承:
.modal:extend(%absolute-center, %fixed-bg),而非写一个巨无霸%modal-base - 避免跨模块继承:不要让
components/_button.less中的:extend指向layout/_grid.less里的类,否则模块耦合变高,迁移困难
编译后体积和浏览器渲染影响
:extend 减少的是 CSS 字节数,但可能轻微增加选择器复杂度:
- 多个类继承同一个基类时,编译结果是逗号分隔的选择器列表(
.base, .a, .b, .c { ... }),CSS 文件体积下降明显,尤其在大量组件复用同一套布局逻辑时 - 过长的选择器链(如
.layout .sidebar .nav-item:extend(.clickable))会让浏览器计算匹配开销上升,建议继承层级控制在 2 层以内 - 继承不会改变 CSS 权重(specificity):如果
.btn:extend(.primary)和.primary同时存在,它们权重相同,后者不会因“被继承”而变弱 - IE8 及更早版本不支持
:extend编译产物中的逗号选择器合并逻辑(实际是 Less 编译阶段完成的,与运行时无关),所以只要编译工具链正常,兼容性无额外风险
真正难处理的从来不是语法怎么写,而是判断「这个样式到底算不算‘可继承’」——它得稳定、无上下文依赖、不随状态频繁变化。一旦把它当 mixin 用,就等于放弃 :extend 最根本的价值。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











