占位符选择器 % 是仅用于 @extend 的静默模板,不输出 css;它比普通类更轻量、无冗余规则,适合抽象不可直接使用的样式层,如重置或布局骨架。

占位符选择器 % 是什么,为什么它比普通类更合适
% 开头的选择器不会被编译进最终 CSS,只作为 @extend 的“模板”存在。它和普通类(比如 .btn)的关键区别在于:普通类一旦被定义,就会原样输出到 CSS 中;而 %button-base 只有在被 @extend 调用时,才把它的样式规则“注入”到目标选择器里。
- 如果你用
.btn-base作基类并@extend .btn-base,结果会多出一条无用的.btn-base{...}规则,污染 CSS -
%button-base则完全静默,只贡献样式逻辑,不增加选择器体积 - 它天然适合抽象“不可直接使用”的样式层,比如重置、布局骨架、视觉状态(
%is-hidden、%flex-center)
@extend %placeholder 和 @mixin 的核心差异在哪
@extend 是选择器级别的合并,@mixin 是声明块级别的复制。
-
@extend %clearfix会让当前选择器“加入”%clearfix所影响的所有规则链,比如.card:after的伪元素样式可能被合并进.list-item的生成规则中(取决于继承路径) -
@include clearfix()只是把那几行声明原样插入,不改变选择器结构,也不产生新的组合选择器 - 当多个选择器都
@extend同一个%,Sass 会智能合并输出——例如.a, .b, .c { clear: both; },而不是重复三遍 - 但
@mixin每次调用都独立展开,容易造成重复声明(尤其在大型组件库中)
哪些场景下 @extend % 会意外放大 CSS 体积
这不是“用了就一定省”,关键看选择器关系是否可控。
- 如果
%base被定义在很深的嵌套层级里(比如.modal .content %base),再被.alert@extend %base,Sass 会生成.modal .content .alert, .alert这类组合选择器,反而更重 - 多个不同命名空间的类同时
@extend同一占位符,且它们本身有复杂父级(如article .post-title和aside .widget-title都 extend%heading),Sass 可能输出冗余的并集选择器 - 使用
!optional不解决根本问题:它只是跳过找不到的占位符报错,但无法阻止已存在的、不合理的继承链
常见错误现象:Warning: You're extending a selector that isn't defined —— 通常是因为 % 定义在局部作用域(如某个 @media 块内)或被 @import 顺序搞乱了
实际写法:一个安全又轻量的 %reset-text 示例
定义要收敛语义、避免嵌套、不带具体尺寸:
%reset-text {
font: inherit;
line-height: inherit;
color: inherit;
margin: 0;
padding: 0;
text-align: inherit;
}
然后在需要“清空文字样式但保留继承”的地方用:
.card-title { @extend %reset-text; font-size: 1.5rem; }button span { @extend %reset-text; }
注意两点:
- 不要给
%reset-text加任何具体值(比如font-size: 1rem),否则失去“重置”本意 - 避免在
%里写&:hover等伪类——除非你明确希望所有 extend 它的类都带上相同交互态,否则极易失控
占位符选择器真正省代码的前提,是你愿意为它设计清晰的抽象边界。一旦开始在 % 里塞媒体查询、伪类、属性选择器,它就不再是“模板”,而成了难以追踪的样式黑洞。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











