直接用.block__element替代.block .element可切断css对html结构的隐式依赖,因后者依赖dom层级易失效,而前者通过命名契约确保样式稳定;常见错误包括单下划线、元素跨块复用、三层嵌套及sass编译失真。

直接用 .block__element 替代 .block .element,就能切断 CSS 对 HTML 结构的隐式依赖——这不是命名习惯问题,是样式能否随 DOM 变动而稳定生效的分水岭。
为什么 .header .nav li a 一改结构就失效
浏览器匹配这个选择器是自右向左:先找所有 a,再逐层往上验证父级是否为 li、.nav、.header。人脑却从左读到右,调试时根本想不到是“a 找多了”还是“.header 少了一层”。更实际的问题包括:
- 把
<li>换成<div>,样式立刻消失,但 HTML 合法、JS 可能还正常运行 <li>第三方组件(比如 <code>react-datepicker)自带.input,塞进.card里会被.card .input意外覆盖 - 多人协作时,A 在
.header加了 padding,B 写的.header .nav突然多出 12px margin——没人知道谁在影响谁 -
block__element中必须是双下划线:button-icon--large是错的——button-icon会被识别为新 block,失去上下文 - element 只能属于且仅属于一个 block:
.modal__close不能同时被dialog和notification复用 - 禁止嵌套 element:
.card__content__title违规,应拆成.card__content和.content__title两个独立 block - Sass 嵌套要小心:
.card { &__content { .item { } } }编译后是.card__content .item,仍违反 BEM 原则 - 锁定最常打架的模块(如
form-item、product-card),把散落的.input、.error、.label全部归入其下:form-item__input、form-item__input--error、form-item__label - HTML 中每个块级容器必须带 block 类:
<div class="form-item">,否则 BEM 失去锚点 <li>CSS 里删掉所有孤立的 <code>.input规则,只保留.form-item__input及其修饰符 - 第三方组件(如
ant-card)不要硬套 BEM,用 wrapper 隔离:<div class="product-card"><div class="ant-card"></div></div>
.block__element 怎么写才不破坏解耦原则
BEM 不是拼下划线,而是靠命名契约守住作用域边界。常见翻车点集中在三类地方:
老项目怎么过渡,又不推倒重来
全局替换类名只会引发样式雪崩。真正可行的路径是「按模块收口」,聚焦高频冲突点:
最容易被忽略的是 display: contents 容器——它会让 DOM 层级“消失”,导致 .block__element 在 DevTools 里看着存在,但样式不生效。这时候必须补上显式 wrapper 或换用 aria-hidden 等替代方案。











