BEM禁止card__header__title等三段式命名,因其违反“元素仅直属于块”的语义规则;正确做法是升维为独立Block(如heading)、用Modifier(heading--in-card-header)或State类(is-subheading),并确保HTML中块类名显式存在。

直接删掉三段式类名,比如 card__header__title 或 nav__item__dropdown——这不是写法问题,是语义断裂的信号。
为什么 card__header__title 是非法命名
BEM 只允许 block__element 和 block--modifier 两种结构。card__header__title 实际在声明 “header 是一个 block”,但它只是 card 的一个 element,不能承载子 element。这种写法会让样式静默失效:
- 改个 DOM 包裹层(比如给
card__header加个<div class="wrapper">),card__header__title就完全不生效 - 无法单独抽离复用:你没法把
card__header__title拿到用户资料页去用,它被当前 HTML 路径锁死了 - DevTools 里搜
title找不到对应样式,因为类名是拼出来的,不是语义化的
该拆成独立 Block 还是加 Modifier
判断标准就一条:这个 UI 片段会不会在别处复用?是否拥有自己的逻辑或样式边界?
- 会复用 → 提为独立 Block:
heading、dropdown、list,各自带__item、__menu - 几乎不复用,但强依赖容器 → 用 Modifier:
heading--in-card-header,而不是card__header__title - 一次性弱复用场景(如折叠面板里的二级标题)→ 用 State 类:
class="heading is-subheading" - 样式高度依赖容器又不想污染命名 → 用
data-context:<div data-context="modal"><button class="button">,对应 CSS:[data-context="modal"] .button
HTML 嵌套深,但类名不能跟着“滑动”
BEM 不要求 HTML 扁平化,只要求类名不随 DOM 层级“滑动”。DOM 可以保持四层甚至五层嵌套,关键在于类名归属是否清晰:
立即学习“前端免费学习笔记(深入)”;
-
card__title是合法的,哪怕它在 DOM 里确实嵌在card__header里 -
card__header__logo是非法的——logo如果只属于card__header,那它仍是card的一部分,应写作card__logo或card__header-logo(后者仅当视觉上构成新语义单元时) - 如果
logo在多个地方复用(比如页头、弹窗、邮件模板),就必须升为独立 Block:logo
容易被忽略的细节:Element 必须显式声明 Block 上的类名
不能只写 <h3 class="card__title">,而要确保父节点有 card 类:<div class="card"><div class="card__header"><h3 class="card__title">。否则 JS 操作 card__title 时会漏掉这个节点——BEM 的作用域隔离,靠的是显式绑定,不是 DOM 路径推导。


















