SCSS中&是字符串拼接操作符而非回退父级:它机械拼接上层选择器,导致类名难读、权重升高、HTML/CSS命名易脱节;应改用@at-root、%placeholder或功能化类名提升可维护性。

SCSS中&不是“回退父级”,而是字符串拼接操作符
你写.card { &__body { } },编译出.card__body;但写成.card { & .body { } },就变成.card .body——中间一个空格,语义全变。这不是语法错误,是选择器关系被你亲手改写了。&不理解缩进、不识别HTML结构,它只忠实地把上一层选择器字符串原样拼上去。一旦嵌套层级变、父选择器加了ID或属性(比如.card[id="main"]),&会照单全收,生成.card[id="main"]__body这种既难读又难搜的类名。
嵌套过深时&放大选择器权重和路径长度
浏览器匹配CSS从右往左,&每参与一次拼接,就可能多带一个空格或关系符,导致最终选择器权重升高、路径变长:
-
.list { & > .item { } }→.list > .item(权重 0,0,2,0) -
.list { .item { } }→.list .item(权重 0,0,2,0,但回溯更深) - 若父级已是
.page .main .content,再嵌&__title,产出.page .main .content__title——看似BEM,实则混合了后代+连写,权重乱、语义断
重构时你得同时改SCSS逻辑、HTML class、甚至JS查询语句,因为document.querySelector('.content__title')和document.querySelector('.content .title')根本不是一回事。
HTML结构微调就会让&拼接结果完全失效
&生成的类名和HTML里写的class必须字面一致,差一个下划线、多一个空格、少一个破折号,样式就挂掉:
立即学习“前端免费学习笔记(深入)”;
- SCSS写
.modal { &--active { } }→ 编译为.modal--active - 但HTML里写的是
class="modal active"→ 不匹配 - 或者写成
class="modal--active is-open",但SCSS里漏了&.is-open→ 状态样式永远不生效
这类问题不会报错,DevTools里也查不到规则被覆盖——它压根没生成,或者生成了但没命中。重构时最容易卡在“为什么这个class明明写了却不起作用”,最后发现是HTML和SCSS的BEM命名约定早就不同步了。
用@at-root或%placeholder替代深层&拼接更可控
想解耦样式与DOM深度,硬撑嵌套只会让重构雪上加霜。真正可维护的做法是主动降层:
- 用
@at-root提级输出工具类:.card { @at-root .u-text-center { text-align: center; } }→ 输出.u-text-center,不带任何父前缀 - 用
%placeholder抽象共性,但必须守死边界:%btn-base { padding: 4px 12px; } .primary-btn { @extend %btn-base; }—— 拓展时不带父上下文,避免生成.card .primary-btn这种冗余链 - 放弃“用嵌套模拟HTML”的执念:CSS该按功能组织(
.is-loading、.has-error),而不是按嵌套几层来写最麻烦的从来不是怎么让
&拼出想要的类名,而是当产品要改一个按钮位置、把.card塞进.sidebar里时,你得翻遍所有&__规则,确认每个&是否还指向同一个“父”——而那个“父”,可能早就不是当初写代码时心里想的那个了。


















