SCSS中&必须显式拼接伪类如&:hover,否则脱离嵌套作用域;伪元素须用&::before,伪类需紧贴&无空格;&仅代表直接父选择器,不跨层追溯。

SCSS中&拼接伪类时必须显式写出&:hover,不能省略&
省略&就等于脱离当前嵌套作用域。比如在.btn块里写:hover,编译后是独立的:hover规则,浏览器直接忽略——它不是合法选择器。只有&:hover才会变成.btn:hover。
常见错误现象:.card { .card__img:hover { ... } } 编译为.card .card__img:hover,这不是“卡片悬停时图片变色”,而是“图片被悬停时才生效”,语义完全错位。
- 伪类必须紧贴
&写,中间不能有空格:&:focus✔️,& :focus❌(后者变成后代选择器) - 多个伪类可连续叠加:
&:hover:focus→.btn:hover:focus - 带括号的伪类如
:is()、:where()也适用:&:is(:hover, :focus)
伪元素必须用&::before,不能写成&:before(冒号数量要对)
&::before和&:before在 SCSS 中都合法,但语义不同:::表示伪元素,:是旧语法别名;现代写法推荐双冒号,避免和伪类混淆。SCSS 不做校验,全靠你手写正确。
容易踩的坑:&:hover::before是合法的(悬停时才显示伪元素),但&::before:hover会编译失败,因为伪元素本身不能响应伪类——CSS 规范禁止。
立即学习“前端免费学习笔记(深入)”;
- 伪元素必须放在伪类之后:
&:hover::after✔️,&::after:hover❌ - BEM 元素+伪元素组合:
&__icon::before→.btn__icon::before,注意&绑定的是整个父选择器字符串 - 不要指望
&自动补全层级:.modal__content { &__title::after { ... } }生成的是.modal__content__title::after,不是.modal__title::after
组合伪类+属性选择器时,&的位置决定最终结构
&不是占位符,它是父选择器的完整展开结果。所以&[disabled]:hover和&:hover[disabled]编译结果一样(.btn[disabled]:hover),但语义优先级不同:前者强调“禁用状态下的悬停”,后者强调“悬停时恰好被禁用”——实际效果相同,但可读性和维护性差很多。
更危险的是混入关系符:.form .field { &[required]::after { ... } } 编译为.form .field[required]::after,权重飙升到 (0,0,1,2),且依赖 DOM 结构,一旦.field不在.form内就失效。
- 属性选择器建议放最后:
&:hover[disabled]比&[disabled]:hover更符合直觉 - 避免在含空格的父选择器里用
&:如.a .b { &[data-foo] { ... } }→.a .b[data-foo],这种选择器浏览器会标黄警告“低效” - 需要交集逻辑(如
button.primary)时,别硬套&.primary,应提至顶层或用@at-root
多层嵌套下&只绑定最近父级,无法跨层引用
&永远只代表当前嵌套层级的**直接父选择器**,不会向上追溯。比如.page { .header { &__logo { ... } } },里面的&指.header,不是.page,所以&__logo编译为.header__logo,而非.page__logo。
这个限制常导致 BEM 命名断裂。想让.header里的元素响应.page--dark状态?不能靠&推导,得把状态类提到.page层级处理:
.page {
&--dark {
.header__logo {
filter: invert(1);
}
}
}
- 没有
&^或&^^语法,SCSS 不支持“祖父选择器” - 想复用父类名拼接不同后缀,只能靠变量或 mixin,不能依赖
&智能识别 - 调试时看编译输出比猜
&行为更可靠——打开.css文件,确认生成的选择器是否是你真正想要的


















