card__header__title是非法的,因BEM仅允许block__element和block--modifier两种结构,三段式命名将card__header误作Block,违背元素必须直属于块的核心规则,导致复用困难、语义断裂及DOM变动时样式静默失效。

card__header__title 是非法的,不是写法问题而是语义崩坏
浏览器不会报错,但 card__header__title 这类三段式命名违反 BEM 核心约束:BEM 只承认 block__element 和 block--modifier 两种结构。出现第三个 __,等于把 card__header 当作新 Block 使用——但它只是 card 的一个 Element,没有独立复用能力、无自身逻辑边界、不能脱离父级 DOM 存活。
常见错误现象包括:
-
card__header__title样式在card__header改为card__section后静默失效 - SCSS 中写
&__header { &__title { } }编译出非法类名,且易误给card__header加 padding,破坏 Element 的纯展示职责 - 想复用该标题到弹窗或用户列表时,发现它被 DOM 路径锁死,无法抽离
三层 DOM 结构下,该挂什么类名?
HTML 可以嵌套五层,但类名归属不看 DOM 深度,而看「是否构成独立 UI 单元」。判断标准只有一条:这个视觉片段会不会在别处复用?有没有自己的样式/交互边界?
实操建议:
- 如果嵌套中的子节点有复用需求(比如列表、下拉项、徽标),就抽成独立 Block:
list、dropdown、badge - 如果只是固定文案、无逻辑、不出现在别处,优先用 Modifier:
card__body-text--subtle,或 State 类:class="text is-in-card-body" - 绝对禁止
card__body__list__item__text这种长名——它暴露的是 DOM 路径,不是组件意图 - Modifier 必须单一职责:
card__title--small✅,card__header__title--small❌(跨层+语义污染)
多级导航菜单怎么命名才不崩?
导航里的下拉菜单不是 nav__item__dropdown,而是一个完整、可独立实例化的 Block。nav 只管布局与语义,dropdown 才管触发、定位、显隐逻辑。
正确结构示例:
<nav class="nav"><ul class="nav__list">
<li class="nav__item">
<a class="nav__link">产品</a>
<div class="dropdown">
<button class="dropdown__toggle"></button>
<div class="dropdown__menu">
<div class="dropdown__item"></div>
<div class="dropdown__item">
<div class="dropdown"> <!-- 二级 dropdown 实例 -->
<button class="dropdown__toggle"></button>
<div class="dropdown__menu"></div>
</div>
</div>
</div>
</div>
</li>
</ul></nav>
关键点:
- 禁止
nav__dropdown、dropdown__menu__submenu、nav__dropdown--level-2 - 每层 dropdown 都是独立实例,通过 DOM 嵌套实现递归,而非类名嵌套
- 修饰符用于行为变体:
dropdown--hover、dropdown--click,不用于标识层级
SCSS 里怎么写才不踩坑?
BEM 本身禁止 CSS 选择器嵌套超过一层,SCSS 的 &__ 和 &-- 是安全的,但一旦出现 &__item &__icon(中间带空格),就生成后代选择器,破坏隔离性。
实操规则:
- 只允许单层嵌套:
.block { &__element {} &--modifier {} } - 禁用
&__element { &__subitem {} }—— 这会产出非法类名 - 若真需控制子元素样式(如
dropdown__menu内的dropdown__item间距),用 Modifier:dropdown__menu--nested或独立布局工具类:u-gap-sm - 所有样式必须由类名驱动,禁用标签选择器(
ul li a)、ID(#header)、属性选择器([data-role="menu"])
真正难的不是记住双下划线怎么写,而是每次加一层 DOM 时,停下来问一句:这个节点有没有自己的功能边界?能不能被抽出来,在用户列表、弹窗、侧边栏里复用?如果答案是肯定的,它就不该挂在父 Block 下,而该拥有自己的 block__element 结构。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











