三层类名如.card__header__title是非法幽灵类名,浏览器无法匹配且引发回溯性能问题;应提级为独立Block并用Modifier扩展,SCSS中&__嵌套必须避免生成后代选择器。

浏览器匹配选择器时会因三层类名触发回溯失效
写 .card__header__title 这类三段式类名,CSS 本身不会报错,但浏览器根本不会按你设想的方式匹配它——因为这个类名根本没在 HTML 中真实存在。你真正写的可能是 <div class="card"><div class="card__header">
<h2 class="card__title">,而 <code>.card__header__title 是个“幽灵类名”,既没绑定 DOM,也没对应任何样式规则。
更危险的是,有人误以为写了这个类名,就该在 CSS 里写 .card__header .card__title,结果生成后代选择器:匹配时先找所有 .card__title,再逐个往上确认父级是不是 .card__header,再确认 .card__header 是否在 .card 内。DOM 节点越多,这个回溯链越长,移动端性能可能直接掉 4 倍。
三层下划线暴露组件职责划分错误
.card__body__list__item 看似只是“多写了两个下划线”,实际说明你把本该独立复用的 list 强行塞进了 card__body 的私有域里。只要 list 在侧边栏、弹窗、表单里也出现过,它就不是元素,而是 Block。
- 正确做法是提级为独立
listBlock,HTML 中写<ul class="list"><li class="list__item"></ul> - 若需卡片内特殊样式,加 Modifier:
list--in-card,而不是靠父级类名推导 - 绝对不要写
.card__body .list这种后代选择器——它让list失去脱离上下文复用的能力
SCSS 里写 &__header &__title 会编译出非法选择器
SCSS 的 & 是父选择器完整副本,不是缩进作用域。写成:
立即学习“前端免费学习笔记(深入)”;
.card {
&__header {
&__title { color: red; }
}
}
编译结果是 .card__header .card__header__title,不仅类名非法(BEM 明确禁止三层),还生成了带空格的后代选择器,权重翻倍、匹配变慢、JS 动态加类极易被覆盖。
合法写法只有一种:
.card {
&__header { }
&__title { }
&--compact { }
}
所有规则都输出单类名,无空格,无回溯,无耦合。
真正容易被忽略的不是“能不能写”,而是“要不要留接口”
每次你犹豫要不要写 block__element__subelement,其实是在回答一个问题:这个 UI 片段,下次出现在另一个页面时,我愿不愿意直接复制粘贴这段 HTML 和 class?
如果答案是否定的,说明它已经具备独立生命周期——该抽成 Block,而不是用嵌套藏起来。BEM 不是命名规范,是组件边界的硬约束;类名长度只是表象,职责模糊才是根因。


















