Element是Block的直系结构部件(如card__title),Modifier是描述状态/变体的可选修饰(如card--featured),二者语义不同、不可互换,且Modifier可修饰Block或Element,但Element不可嵌套。

Element 和 Modifier 看似只差两个字符(__ vs --),但语义和使用逻辑完全不同——混淆它们会导致样式失控、复用困难,甚至让团队协作踩坑。
Element 是“谁的什么部分”,不是“什么状态”
Element 描述的是结构归属关系:它必须属于某个 Block,且是该 Block 的直系组成部分。比如 card__title 合法,因为 title 是 card 的一部分;但 card__image__caption 违规,caption 不是 card 的直系子元素,而是 image 的子内容——BEM 不允许这种嵌套层级。
常见误用场景:
- 把按钮点击后的 loading 状态写成
button__loading(错误:loading 是状态,不是 button 的固有结构部件) - 给弹窗里的关闭图标起名
modal__close__icon(错误:close 已是 element,icon 再嵌套就破坏 BEM 层级) - 在 Vue 中把子组件类名硬套成
form__input__error-message(错误:error-message 应该是form__input--error或独立 block)
Modifier 表达“变体”,必须依附于 Block 或 Element
Modifier 从不单独存在,它永远修饰已有结构:button--disabled 修饰 block,input--focused 修饰 element。它的作用是描述外观、行为或状态差异,而不是新增结构。
立即学习“前端免费学习笔记(深入)”;
关键判断点:
- 这个类名是否能被移除而不影响 DOM 结构完整性?如果能,大概率是 Modifier
- 是否只在特定条件下动态添加/移除(如 JS 控制的
is-open、has-error)?那它更适合用 Modifier - 是否需要覆盖默认样式(颜色、尺寸、边框、显示隐藏)?这是 Modifier 的典型职责
示例对比:
.card { /* 基础卡片 */ }
.card__title { /* 卡片标题,结构必需 */ }
.card--featured { /* 特色卡片,视觉强化,可选 */ }
.card__title--large { /* 标题变大,仅当标题本身有“大号”这一变体时才用 */ }实际项目中怎么一眼分清?看命名和用途双验证
遇到一个类名,先看符号分隔:
- 含
__→ 检查它是否对应 HTML 中某个 Block 下的直系子节点(如<div class="card"> <h3 class="card__title">)</h3> <li>含 <code>--→ 检查它是否表达一种可切换的状态(menu--collapsed)、尺寸(button--small)、主题(form--dark)或行为(tab--active) - 这个类是否出现在所有同类 Block 中?如果是(如每个
card都有card__title),那就是 Element - 这个类是否只在某些实例中出现?比如只有“禁用按钮”才有
button--disabled,那就是 Modifier
再看用途:
容易忽略的一点:Modifier 可以修饰 Element,但不能反过来。你可以说 input__label--required,但不能说 input--required__label——后者语法非法,语义混乱。


















