占位符必须定义在顶层且平级独立,不能嵌套;@extend引用需在定义之后,跨文件须显式加载;伪类内不可用@extend;推荐@mixin或HTML多类组合替代。
占位符选择器 %btn-focus 如果写在另一个选择器(比如 %button-base)内部,Sass 就不会把它当作独立可扩展的锚点——它成了“复杂选择器的一部分”,编译时直接被忽略。这不是 bug,是 Sass 的明确限制:任何包含占位符的选择器都不能再被嵌套。
%button-base { %btn-focus { color: blue; } } → %btn-focus 永远不会生效% 占位符必须平级定义,彼此独立% 名字,说明它没被识别为合法占位符Sass 编译是单向顺序解析的,@extend %xxx 出现的位置,必须在 %xxx 定义之后。跨文件引用时,@use 或 @import 必须显式加载定义文件,不能靠“文件名靠前就自动可用”这种猜测。
Invalid CSS after "": expected selector, was "}" → 很可能是因为 %xxx 还没被读到就尝试 @extend
@use "base" as * 才能让 %base-focus 在当前文件可用@extend 放在同一个 mixin 或循环里,作用域会干扰解析顺序:focus、.focus、:hover 这类状态规则本身不能作为占位符的父容器,也不能让占位符“藏在里面”。想让按钮获得焦点样式,得把状态逻辑拆出来,单独定义占位符并显式扩展。
%btn { &:focus { @extend %focus-style; } } → %focus-style 不会被识别%btn-focus { color: white; outline: 2px solid #007bff; } .btn:focus { @extend %btn-focus; } .btn.focus { @extend %btn-focus; }
&:focus 嵌套写法,那里面写的 @extend 是无效的——Sass 不允许在伪类块内扩展占位符占位符 + @extend 本质是“选择器合并”,一旦涉及响应式、伪类、多层嵌套,很容易失控。真正稳定的复用方式不是继承,而是组合或封装。
@mixin:比如 @mixin focus-state($color) { &:focus, &.focus { color: $color; } },调用清晰、无副作用class="btn btn--primary btn--focusable",CSS 写 .btn--focusable:focus,不依赖 Sass 编译逻辑%sr-only、%clearfix 这类无语义、无上下文的规则用 @extend,避免污染业务选择器