bem禁止card__header__title这类三层命名,因其违反element必须直属于block的核心规则;正确做法是将title升格为独立block(如heading)、用modifier(heading--in-card-header)表达上下文,或借助data属性锚定样式。

不能用 card__header__title 这类三层命名,BEM 明确禁止 Block__Element__Element 结构——它不是浏览器报错的问题,而是直接破坏复用性、测试性和协作安全性的设计越界。
为什么 card__header__title 是非法 BEM 类名
BEM 的 Element 必须**直接隶属于 Block**,card__header 本身已是 Element,不能再作为父级承载另一个 Element。card__header__title 看似反映 DOM 层级,实则混淆了“结构归属”和“视觉嵌套”:HTML 可以有三层 div 嵌套,但 class 名必须扁平到块级边界。
- 编译后无法被
stylelint-selector-bem-pattern通过,CI 阶段会被拦截 - SCSS 中写
.card { &__header { &__title {} } }会产出非法名,且实际生成的是后代选择器(.card .card__header .card__header__title),权重失控 - 抽离
title样式时无处下手——它没有独立类名,无法单独测、单独改、单独复用
孙子节点场景下该用哪个 Block
遇到 <div class="card"><div class="card__header">
<h2 class="???"> 这种结构,关键不是“怎么给 h2 起名”,而是判断这个 h2 是否具备独立语义:
<ul>
<li>如果它在用户页、弹窗、侧边栏都出现,且字号/颜色/行高基本一致 → 它是独立 Block:<code>heading
heading--in-card-header,再靠父级微调布局card__header-title?不,正确做法是把整个 header 提升为 Block:card-header,然后 card-header__title
SCSS 里怎么写才不偷偷造出孙子名
所有嵌套必须显式提级,禁用 &__xxx 在非根级上下文中使用。常见错误是以为 & 总能取到块名,其实它取的是完整父选择器字符串,含空格即失效。
- ❌ 错误:
.card { .card__header { &__title {} } }→ 编译为.card .card__header__title - ✅ 正确:
.card { @at-root #{&}__header-title {} }→.card__header-title(注意这里已将 header-title 视为 card 的直系 Element) - ✅ 更推荐:
.heading { @at-root #{&}--in-card-header {} }+ HTML 中写<h2 class="heading heading--in-card-header"></h2> - 工具链兜底:配置
stylelint-selector-bem-pattern,规则设为/^[a-z][a-z0-9]*(-[a-z0-9]+)*(__[a-z][a-z0-9]*(-[a-z0-9]+)*)?(--[a-z][a-z0-9]*(-[a-z0-9]+)*)?$/,自动拦截含两个以上__的类名
真需要上下文强绑定时怎么办
极少数情况,如折叠面板里的二级标题、弹窗 footer 中的按钮组,它们几乎从不在别处复用,且样式高度依赖容器位置和状态——这时优先用 State 类或 data 属性,而非硬编码孙子结构:
- 用
is-subheading这类状态类:<h3 class="heading is-subheading"></h3>,配合.is-subheading { font-size: 0.9em; margin-top: 0.5em; } - 用
data-context:<div data-context="modal-footer"><button class="button">,再写 <code>[data-context="modal-footer"] .button { padding: 4px 8px; } - 避免
.modal__footer .button这种后代选择器——它违背 BEM 单类名原则,且一旦 modal 结构微调,样式就断
最易被忽略的一点:BEM 扁平化不是为了“让类名变短”,而是为了让每个类名都能被独立定位、独立测试、独立删除。一旦你发现某个类名删了不敢提交,那它大概率已经踩进了孙子陷阱。











