SCSS中&只引用最近父选择器,非自动拼接:&:hover编译为.parent:hover;BEM修饰写&--mod而非&.mod;状态联动需将状态类作为父容器嵌套;&不支持跨层引用,无&^语法;与:is()混用时需注意兼容性。

SCSS中&符号怎么正确引用父选择器?
直接用 & 就能拿到上层选择器的完整字符串,但它不是“自动拼接”,而是原样复用——这点最容易出错。比如嵌套在 .card 下的 &:hover 编译后是 .card:hover,不是 .card .card:hover。
常见错误是误以为 & 会自动补全层级,结果写出 & &--active,编译成 .btn .btn--active(带空格,变成后代选择器),而实际想要的是 .btn--active(同级修饰类)。
- 想生成 BEM 风格的修饰类:写
&--active,不是&.active - 想加伪类或属性选择器:直接跟在
&后,如&:focus、&[disabled] - 想组合多个父级(如同时作用于
.theme-dark和.card):必须显式嵌套,&只绑定最近一层父选择器
如何用&实现父子类名联动(比如状态响应)?
典型场景:组件有基础类 .button,点击后加 .is-loading,希望此时内部图标旋转、文字变灰。不能靠 JS 动态加 class 再写一堆独立规则,而是用 SCSS 提前定义好联动关系。
关键点在于:把状态类作为父容器类来嵌套,而不是单独写一个选择器。例如:
立即学习“前端免费学习笔记(深入)”;
.button {
&.is-loading {
color: #999;
pointer-events: none;
.button__icon {
animation: spin 1s infinite;
}
}
}
这样编译后是 .button.is-loading + .button.is-loading .button__icon,确保样式只在状态激活时生效,且不污染全局。
- 不要写成
.button .is-loading(后代选择器,语义错、易冲突) - 如果状态类在更外层(如
.page--busy .button),就该在外层嵌套,&仍只响应最近父级 - 多个状态叠加(如
.button.is-loading.is-disabled):用&.is-loading.is-disabled,顺序无关,但类名必须同时存在
为什么&不能跨多层引用上级类名?
SCSS 的 & 只绑定当前嵌套层级的直接父选择器,没有“祖父”或“祖先”语法。比如:
.modal {
.modal__content {
& .modal__title { ... } // 编译为 .modal .modal__content .modal__title
}
}
这里的 & 指的是 .modal__content,不是 .modal。想让 .modal__title 响应 .modal--fullscreen 状态,必须把状态类放在 .modal 上,并在顶层处理:
.modal {
&--fullscreen {
.modal__content {
height: 100vh;
}
}
}
否则就得手动重复写 .modal--fullscreen .modal__title,失去嵌套优势。
- 没有
&^或&..这种语法,别搜了 - 真需要跨层耦合,考虑用
@at-root提升选择器,但会破坏结构可读性 - 更稳妥的做法:把状态类尽量往上提,靠近组件根节点
和 CSS 原生 :where() / :is() 联动时要注意什么?
现在有人会混用 SCSS & 和 CSS 新伪类,比如写 &:is(:hover, :focus)。这本身合法,但要注意编译结果:
&:is(:hover, :focus) 编译后是 .btn:is(:hover, :focus),而浏览器支持度取决于目标环境(Safari 15.4+、Chrome 101+)。如果要兼容旧版,得拆成 &:hover, &:focus。
-
:where()会重置优先级,但&:where(.active)编译后仍是.btn:where(.active),优先级没变,别指望它降权 - 避免在
&后直接接复杂选择器链,比如& > li:first-child—— 可读性差,也难维护 - 构建工具(如 vite + postcss)若启用了 autoprefixer,
:is()类可能被降级展开,此时&的行为不变,但输出体积变大
真正容易被忽略的,是 & 在混合宏(@mixin)里的行为:它只在调用位置生效,不是定义位置。也就是说,& 的指向永远取决于你把它写在哪一层嵌套里,而不是它被定义在哪。


















