bem规范禁止三层及以上类名如card__header__title,因其违反block__element结构、导致语义失效、复用困难及样式锁死;深层嵌套应按复用性判断是否抽离为新block。

直接禁止三层及以上类名,card__header__title 这类写法不是风格偏好问题,而是语义失效的明确信号。
为什么 card__header__title 是非法类名
BEM 规范只允许 block__element 和 block--modifier 两种结构。出现第三个 __,等于把 card__header 当作新 Block 使用——但它本身只是 card 的一个 Element,没有资格承载子元素。
- DOM 结构一变(比如
card__header被重命名为card__section),card__header__title样式就静默失效 - 无法单独复用或测试这个类名,它被 DOM 路径锁死
- SCSS 中写
&__header { &__title { } }会编译出非法类名,还容易误给card__header加 padding,破坏 Element 的纯展示语义
遇到深层 DOM 嵌套时,该不该抽新 Block
判断标准不是“HTML 嵌套了几层”,而是“这个 UI 片段会不会在别处复用?是否拥有自己的逻辑或样式边界?”
- 如果
list在用户列表、搜索结果、侧边栏都出现 → 应定义为独立listBlock - 如果
list__item需要点开展开、有独立动画或状态管理 → 它更不该依附于card - 如果只是卡片内一段固定文案,且绝不出现在别处 → 可改用 Modifier 或 State 类,如
card__body-text--subtle或class="text is-in-card-body"
Sass 嵌套中哪些写法会悄悄破坏 BEM
Sass 的缩进容易掩盖语义错误,真正安全的只有三类 & 写法:&__element、&--modifier、&:hover(且需配合 JS 切换类名)。
-
.card { &:hover { &__icon { } } }编译出.card:hover .card__icon,含空格,违背扁平性 -
.card { .header { &__title { } } }编译出.header__title,语义全错 - 嵌套超过 3 层(如
.card { &__header { &__title { &--small { } } } })必须重构,删掉最内层,改用单类名card__title--small或独立 Block - 媒体查询必须用
@at-root提级,否则.card { @media (max-width: 768px) { &__title { } } }会编译无效规则
修饰符命名和 State 类怎么选才不越界
Modifier 不是用来补层级缺口的,而是表达有限、可枚举的状态变体;State 类或 data- 属性更适合一次性、强上下文依赖的场景。
-
heading--in-card-header:适合字体缩小 10%、行高微调等明确变体,且该变体在多个容器中复用 -
is-subheading:适合折叠面板里的二级标题这类一次性场景,CSS 写.is-subheading { font-size: 0.9em; } -
data-context="modal":适合样式高度依赖容器但又不想污染 Block 命名,CSS 写[data-context="modal"] .button { padding: 4px 12px; } - 绝对禁止
card__header__title--small:这等于把两层语义塞进一个 Modifier,违反单一职责原则
真正难的不是写对名字,而是每次加一个 __ 之前,停下来问一句:这个东西,以后会不会被别人从 card 里抽出来用?
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











