bem禁止card__header__title这类三层命名,因其违反“元素仅属块直系”的核心规则;正确做法是将title设为独立block(如heading)或用modifier(heading--in-card-header)及父级微调布局。

card__header__title 这种写法为什么直接报错
它根本不是合法 BEM 类名,BEM 规范明确禁止 Block__Element__Element 结构。card__header__title 暗示“title 是 header 的子元素”,但 header 本身只是 card 的一个 Element,不能作为父级承载另一个 Element。浏览器不会报错,但团队协作、组件抽离、样式复用会立刻崩坏——你没法单独测试或复用这个 title,它被死死绑在 card__header 的 DOM 结构里。
遇到 DOM 有三层嵌套,HTML 怎么写才不破环 BEM
别让 HTML 结构牵着 CSS 走。真实 DOM 可以是 <div class="card"><div class="card__header">
<h2 class="header-title">,关键在类名归属:
<ul>
<li>
<code>header-title 应该是一个独立 Block(比如 heading 或 section-title),而不是 card 的子孙
heading--in-card-header
.card__header .heading { margin-bottom: 8px; } —— 这种嵌套仅限一层,且只用于布局微调,不定义核心样式SCSS 里写 &__header &__header__title 会出什么问题
这种嵌套写法在 SCSS 编译后会生成非法类名,而且极易误判作用域:
-
&__header__title编译成.card__header__title,违反 BEM 基本规则 - 开发者容易以为
&__header是个“容器块”,继而给它加 padding/margin,结果破坏了card__header作为纯 Element 的语义 - 一旦把
header__title拆成独立 Block,所有 SCSS 嵌套逻辑得重写,维护成本翻倍 - 正确做法:SCSS 中每个 Block 单独定义,
heading和card各自维护,用@use或文件引用组织依赖
什么情况下真需要表达“孙子”关系,又不想新增 Block
极少数场景下,比如折叠面板里的二级标题、弹窗 footer 中的按钮组,它们几乎从不在别处复用,且样式高度依赖容器。这时优先用 State 类或 data 属性,而非造新 Block:
- 给标题加
class="heading is-subheading",再写.is-subheading { font-size: 0.9em; } - 用
data-context="accordion"标记容器:<div data-context="accordion"> <h3 class="heading">,对应 CSS:<code>[data-context="accordion"] .heading { margin-top: 4px; } - 避免
card__body__button-group这类命名——它既搜不到,也切不出,还让 button-group 失去语义独立性
真正难的不是写对类名,而是每次看到三层 DOM 就条件反射想加第三层下划线。克制住那一刻,先问:这个 UI 片段,会不会出现在用户头像旁?会不会在通知卡片里重复?答案只要有一个“会”,它就必须是 Block。











