%placeholder是sass中不输出css的选择器,仅用于@extend内联合并样式;而.class是真实类名,未使用也会编译进css,易造成冗余和污染。

什么是 %placeholder,它和 .class 有什么本质区别
%placeholder 不会直接编译成 CSS,只在 @extend 时被“注入”到目标选择器中。而 .class 是真实存在的类名,哪怕没被用也会输出到 CSS 文件里。
这意味着:用 %placeholder 可以定义样式骨架,却不污染最终的 CSS 体积;但一旦写错引用方式(比如直接在 HTML 里加 class="%foo"),浏览器完全不认识——它根本不是类名。
-
%btn-base定义了 padding、border、cursor 等共性,但不生成任何 CSS 规则 -
.btn-primary {@extend %btn-base;}才真正把样式合并进.btn-primary - 如果误写
.btn-primary {@extend .btn-base;},Sass 会报错:Base class ".btn-base" is not defined
什么时候该用 %placeholder,而不是 @mixin
核心判断点:是否需要复用“静态样式组合”,且这些样式**永远不单独存在**。
@mixin 适合带参数、需动态计算的场景(比如 @mixin responsive-font($size));%placeholder 更适合纯声明式、可被多处无差别继承的视觉模式(比如表单控件重置、清浮动、禁用态统一处理)。
- ✅ 推荐用
%placeholder:%visually-hidden、%clearfix、%sr-only - ❌ 别用
%placeholder:%shadow-sm(不同组件可能需要不同box-shadow值,应改用@mixin shadow($level)) - ⚠️ 注意:Sass 3.4+ 支持
@extend跨文件,但必须先@import或@use含占位符的文件,否则报错Undefined placeholder selector "%xxx"
@extend 的连锁扩展风险与规避方法
一个 %placeholder 被多次 @extend,Sass 默认会把所有引用它的选择器合并成一条规则——这看似省代码,实则容易触发“选择器爆炸”。比如 10 个组件都 @extend %reset,最终 CSS 里可能出现长达数行的选择器列表,影响渲染性能和可维护性。
- 用
@extend %placeholder !optional避免因占位符未定义导致编译失败(调试期有用,上线前建议删掉) - 对高频复用的占位符,提前用
%placeholder+@at-root控制输出位置,避免嵌套过深时生成冗余父级前缀 - 更稳妥的做法:把真正通用的原子样式(如
display: block、margin: 0)抽成%reset-atom,而非一个大而全的%reset-all
和 CSS 自定义属性(--var)不是替代关系,而是协作关系
%placeholder 解决的是“样式结构复用”,CSS 变量解决的是“值动态替换”。两者可以共存,但不能混用逻辑。
- 错误示范:
%btn { --bg: #007bff; background-color: var(--bg); }—— 占位符里定义变量,但变量作用域不会随@extend传递,子选择器无法覆盖 - 正确协作:
%btn-base { padding: 0.375rem 0.75rem; } .btn { @extend %btn-base; --btn-bg: #007bff; background-color: var(--btn-bg); } - 关键提醒:Sass 编译阶段变量已被计算完毕,
var(--x)是运行时行为,@extend无法介入其解析过程
真正难的不是写对 %placeholder,而是判断哪些样式“值得抽象为占位符”——它必须足够稳定、足够通用,又不能太宽泛。一个占位符一旦被广泛 @extend,后续修改就会影响所有下游选择器,这种隐式依赖比 @mixin 更难追踪。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











