应优先用@extend当多个选择器需完全共享固定样式且无参数需求,如.btn-primary和.btn-secondary继承.base-btn的边框、内边距等;而需传参(颜色、尺寸)、响应式嵌套或动态值时必须用@mixin。

什么时候该用 @extend 而不是 @mixin
当多个选择器需要完全共享同一组样式规则,且不涉及动态参数时,@extend 更合适。比如按钮变体(.btn-primary、.btn-secondary)都继承基础 .btn 的边框、内边距、字体等固定属性——这时用 @extend 生成的 CSS 更紧凑;而一旦需要传入颜色、尺寸等变量,就得切回 @mixin。
常见错误是强行用 @extend 替代 @mixin 来“复用带参数的样式”,结果编译报错或输出不可预期的选择器组合。
-
@extend只能继承已存在的选择器(如.btn),不能继承占位符选择器以外的抽象定义(除非用%placeholder) - 被继承的选择器必须在当前作用域可见,跨文件需确保
@import顺序正确 - 若目标选择器含复杂组合器(如
article h2),@extend会把整个链路复制过去,容易污染语义
@extend 和占位符选择器 % 的配合用法
占位符选择器 %reset-list 是 @extend 的安全搭档:它不会被编译成 CSS,只作为“纯样式骨架”供继承,避免无意义的冗余类名泄漏到最终 CSS 中。
比如重置列表样式:
立即学习“前端免费学习笔记(深入)”;
%reset-list {
margin: 0;
padding: 0;
list-style: none;
}
.nav-menu {
@extend %reset-list;
display: flex;
}
这样 .nav-menu 就获得了重置样式,但最终 CSS 里不会有 %reset-list 这个类名,也不会多出一条空规则。
- 别把
%当作普通类写进 HTML——它根本不会出现在浏览器里 - 一个
%可被多次@extend,Sass 会智能合并相同声明,减少重复输出 - 如果多个占位符之间有依赖(如
%btn-base继承%reset-inline),注意@extend链不能循环
@extend 编译后选择器爆炸的真实风险
Sass 为保证样式优先级和覆盖逻辑,会把所有继承关系展开成完整选择器链。比如 .sidebar .widget 继承 .card,再被 .dashboard .stats 继承,最终可能生成类似 .sidebar .widget, .dashboard .stats 的并列选择器——看起来没问题,但若嵌套过深或继承层级过多,CSS 文件体积和浏览器匹配开销会明显上升。
- 用
sass --watch编译后检查输出 CSS,确认没有意外的长选择器(如.header nav ul li a:hover被重复拼接了三次) - 避免在媒体查询内部过度使用
@extend,不同断点下的继承可能生成大量冗余组合 - 当发现 CSS 文件比预期大很多,优先排查
@extend的使用位置,而不是直接归因于源码行数
为什么 @extend 无法跨模块干净复用
@extend 不是“导入样式”,而是“要求编译器把当前选择器加入目标选择器的输出列表”。这意味着:如果模块 A 定义了 .btn,模块 B 想 @extend .btn,就必须确保 A 的 .btn 在 B 编译前已被加载(通过 @import 或 @use),且不能被 @at-root 或其他作用域操作隔离。
更麻烦的是,Sass 6.0+ 推荐用 @use,但它默认启用模块私有作用域——.btn 不会自动暴露给其他模块,必须显式用 @forward 或 public 标记。
- 用
@use "base" as *;可临时绕过命名空间,但破坏封装性,不推荐长期使用 - 想跨模块安全复用,优先考虑把公共样式抽成
%占位符 +@forward,而非依赖具体类名 - 如果团队已迁移到
@use,却还在各处写@extend .something,大概率会遇到 “Undefined mixin” 类似报错——其实是选择器未暴露,不是拼写问题
真正难的不是语法,是搞清 Sass 编译时的符号可见性边界。一次没导出,全链路就断掉。


















