&符号代表父选择器的完整展开结果,保留空格及>、+等关系符,非字符串拼接;滥用会导致语义错误、性能警告或样式失效,如.nav__item__link误代.nav__item a。

& 不是拼接符,而是父选择器的完整展开结果;滥用链式调用会生成语义错误、性能警告甚至失效的选择器。
为什么 & 在嵌套中会展开成带空格或关系符的选择器
SCSS 的 & 不做字符串拼接,它代表外层选择器在编译时的**实际 CSS 输出形态**。比如:.card > .header 是一个子元素选择器,那么 &__title 就会变成 .card > .header__title,中间的 > 被原样保留。
常见错误现象:.nav { &__item { &__link { } } } 编译为 .nav__item__link,但真实 DOM 中 a 标签往往只是 .nav__item 的后代(非直接子元素),导致样式不生效。
- 父选择器含空格(如
.modal .content)→&__body生成.modal .content__body,这不是合法的 BEM 命名,且浏览器会警告“复杂后代选择器” - 父选择器含
+、~、>→&:hover仍会保留关系符,例如.item + .item:hover,逻辑上可能完全错位 - 想写
.nav__item a,必须显式写出a,不能靠& a或&a—— 后者会被编译成.nav__itema(无空格,类名错误)
如何正确生成交集选择器(如 button.primary 或 input[type="text"])
SCSS 嵌套中无法用 &.primary 模拟交集选择器,因为 & 指向的是外层选择器整体,而 .primary 是独立类名,二者不是嵌套关系。
错误写法:.btn { &.primary { ... } } → 编译为 .btn.btn.primary(多了一个 .btn, specificity 过高且语义冗余)。
- 交集规则必须提至顶层,或用
@at-root脱离嵌套上下文:@at-root button.primary { background: #007bff; } - 属性选择器同理:
@at-root input[type="submit"] { padding: 8px 16px; },避免嵌套后变成.form input[type="submit"]这类过长选择器 - 多个组件共用同一组交集规则?抽成
@mixin,而不是靠&硬连 —— 比如@mixin focus-outline { &:focus { outline: 2px solid #007bff; } }
并集选择器(逗号分隔)和深层嵌套的控制线
逗号分隔的并集选择器(如 h1, h2, .title)完全无法用 & 生成,必须手写。SCSS 不支持 “用嵌套一次产出多个顶层选择器”。
嵌套深度直接影响编译后选择器长度与 specificity。三层嵌套(如 .modal .content .body p)已接近可读与性能临界点;四层开始,Chrome 开发者工具会标黄提示“选择器过长”,Firefox 可能触发重排降级。
- 避免
.component { .header { .title { .icon { ... } } } }这类写法;改用扁平化命名或模块拆分 - 需要组合多个父级上下文?优先考虑用
@extend或@mixin复用,而非加深嵌套 - 真要写复合关系(如
.card:hover .card__title),直接在顶层写清楚,别指望&:hover &__title—— 它会编译成.card:hover .card__title,看似对,但&__title的展开依赖外层,一旦挪动位置就容易出错
真正难的不是语法,而是判断哪些关系该由 HTML 结构承载,哪些该由 SCSS 命名约定表达;& 很方便,但它的展开行为是“忠实复刻”,不是“智能推导”。一不留神,就写出浏览器都懒得优化的选择器。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











