BEM 规范禁止用双下划线连接嵌套 Block,Element(__)仅用于同一 Block 内部,跨 Block 应保持独立命名并依赖 DOM 结构与 CSS 层级选择器实现上下文限定,必要时使用语义化 Modifier(如 nav--inline)而非拼接类名。

Block 嵌套时不能用双下划线连接子 Block
BEM 规范里,__(双下划线)严格用于表示 Element,不是用来连接两个 Block 的。比如 header__nav 是合法的(nav 是 header 的 Element),但如果你把 nav 本身也当作一个独立 Block(有自己的一套 nav__item、nav--active),那它就不该依附于 header 的命名空间。
常见错误是写成 header__nav__item 或 header__nav--mobile——这会让 nav 失去语义独立性,也破坏了 Block 可复用的前提。
嵌套 Block 应保持顶层命名,通过 DOM 结构体现层级
真正要表达“导航在页头里”,靠的是 HTML 嵌套,而不是类名拼接。只要结构清晰,样式可以通过 CSS 层级选择器控制:
<header class="header">
<nav class="nav">
<ul class="nav__list">
<li class="nav__item"><a class="nav__link">首页</a></li>
</ul>
</nav>
</header>对应 CSS 中需要限定作用域时,写成:
立即学习“前端免费学习笔记(深入)”;
.header .nav { /* 仅在 header 内生效的 nav 样式 */ }
.header .nav__item { /* 特定上下文下的 item 样式覆盖 */ }- 这样
nav仍是完整可复用的 Block,能用在footer或aside里 -
.header .nav__item是修饰行为,不是定义新类名,不污染 BEM 命名空间 - 避免用
header__nav这种“伪 Block”导致后续无法单独维护nav
需要上下文强绑定时,用 Modifier 而非嵌套命名
如果某个 Block 在特定父容器中表现完全不同(比如 nav 在 header 里是横排,在 footer 里是竖排),应该用 Modifier 表达差异,而不是改类名:
<header class="header"> <nav class="nav nav--inline"></nav> </header> <footer class="footer"> <nav class="nav nav--stacked"></nav> </footer>
这样既保留了 nav 的一致性,又明确表达了变体意图。
-
nav--inline和nav--stacked是同一 Block 的状态变体,不是新 Block - 比
header__nav+footer__nav更易维护、更利于组件抽离 - 注意 Modifier 名称要语义化,避免出现
nav--in-header这种依赖位置的描述
警惕 “Block 套 Block” 导致的样式耦合
实际项目中最容易被忽略的点是:看似合理的嵌套命名,会悄悄让样式逻辑和 DOM 位置强绑定。一旦需求变化(比如要把 nav 提到 body 顶部做全局导航),所有 header__nav* 类都要重写,CSS 也要大面积调整。
真正的 BEM 弹性来自 Block 的自治性——每个 Block 应该能独立存在、独立测试、独立复用。所谓“嵌套”,只是视觉或语义上的,不是命名上的。
如果你发现必须靠类名嵌套才能准确选中元素,大概率是结构设计或职责划分出了问题,而不是 BEM 写法需要妥协。


















