别用 @extend 优化 BEM,它会导致 CSS 体积膨胀且阻碍 PurgeCSS 等工具识别未用类;应改用 @mixin 封装可复用样式,保持类名独立、语义清晰、压缩友好。

别用 @extend 优化 BEM —— 它会把体积撑得更大,还埋下维护雷。
为什么@extend和BEM一起用反而膨胀CSS
@extend 的本质是静态选择器合并,而 BEM 要求每个类名语义独立、可预测。两者逻辑冲突:
- 当你在
.card__title {@extend %text-emphasis;}里用@extend,Sass 会把所有匹配%text-emphasis的规则“复制”进.card__title,同时还要为.list__item {@extend %text-emphasis;}再复制一遍——哪怕样式声明完全相同,也会生成两条独立规则 - BEM 类名本应复用,但
@extend让编译器无法识别这种复用意图;工具如postcss-discard-unused看到的是两个不同选择器,不敢删 - 如果
%text-emphasis本身含伪类(如&:hover)或嵌套上下文(如.card &),@extend会触发组合爆炸,一条占位符可能产出十几条变体规则
真正轻量的BEM写法:不用@extend,改用@mixin + 单类名复用
保持 BEM 的单类名结构,把重复样式逻辑封装进 @mixin,再由各组件显式调用:
// _mixins.scss
@mixin text-emphasis {
font-weight: 600;
color: var(--text-primary);
line-height: 1.4;
}
// card.scss
.card__title {
@include text-emphasis;
font-size: 1.25rem;
}
// list.scss
.list__item {
@include text-emphasis;
font-size: 1rem;
}
-
@mixin只复制声明,不复制选择器,最终 CSS 里仍是两个独立类名,但样式块内容一致,利于后续压缩和 gzip - 所有调用点清晰可见,JS 层(如
clsx)能准确识别哪些类名被用了,PurgeCSS 才敢删未用类 - 需要传参时(比如颜色、尺寸),
@mixin天然支持;@extend完全做不到
如果非要用@extend,必须满足这三个硬条件
极少数场景(如统一过渡、重置基础属性)可谨慎用 @extend,但必须卡死边界:
立即学习“前端免费学习笔记(深入)”;
- 只继承
%placeholder,绝不用真实类名(如.btn)——防止无意义类名泄露到输出 CSS - 占位符定义必须在同一个文件或明确受控的模块内,禁止跨组件
@extend(比如card.scss去@extend %flex-center来自layout.scss) - 占位符内部不能含任何上下文(如
&:hover、@media、.parent &),否则编译后规则数指数增长
最常被忽略的一点:BEM 的价值不在“写得少”,而在“删得准”。一旦引入 @extend,就等于主动放弃 PurgeCSS 和 tree-shaking 的识别能力——体积问题会从构建阶段,一路拖到线上运行时才暴露出来。


















