Block是可独立交付、有明确业务语义的功能单元;Element必须依附Block、不可单独使用;Modifier仅描述状态且永不脱离被修饰对象。

Block 是能独立交付、不依赖上下文的功能单元;Element 必须依附 Block 存在、不可嵌套、不能单独使用;Modifier 只描述状态或变体,永远不脱离它所修饰的 Block 或 Element。
怎么一眼认出哪个是 Block
看它能不能被复制粘贴到另一个页面、删掉后其他功能是否仍可运行、有没有明确的业务语义(比如 search-form 对应 PRD 里的“搜索框”需求)。不是所有视觉容器都是 Block —— main-content、section-2 这类带位置或结构暗示的名字,本质只是布局占位,不是 Block。
常见误判包括:
- 把 HTML 标签名当 Block:
header、footer看似合理,但一旦抽成独立组件,header__logo和footer__logo就可能样式冲突,真正该拆的是logo这个可复用块 - 用形容词或值命名:
big-card错误,尺寸应由 Modifier 控制;user-profile-compact错误,紧凑态应写作user-profile--compact - 加冗余前缀:
user-profile__user-profile-avatar❌,正确是user-profile__avatar
Element 为什么不能单独写 class
card__title 这类类名没有独立语义,它的样式和行为都绑定在 card 上。脱离 card 容器单独使用,CSS 选择器大概率失效,JS 逻辑也可能错位。
立即学习“前端免费学习笔记(深入)”;
判断一个东西是不是 Element,只看三点:
- 它是否天然属于某个 Block?比如
menu__item离开menu就失去导航上下文 - 它是否具备独立复用价值?如果头像旁的 VIP 徽标有点击行为、跨页面出现,那它不该是
user-profile__avatar__vip,而应升为独立 Block:badge - 命名是否符合
block__element格式?双下划线__不可省略、不可替换为_或-;多单词用短横线:form__submit-button✅,form__submitButton❌
Modifier 什么时候必须用 --,什么时候不该加
-- 是 Modifier 的硬性标识符,只用于表达布尔状态或有限变体,比如加载中、禁用、暗色模式。它永远不单独存在,必须紧贴被修饰对象:button--disabled、card__image--rounded。
容易踩的坑:
- 把具体值塞进 Modifier:
button--width-200❌,宽度应由 CSS 自定义属性或布局系统控制 - 堆叠多个 Modifier:
card--compact--dark--bordered❌,这会快速失控,建议收敛到card内部用--控制状态,外观细节交由 CSS 变量管理 - 用 Modifier 替代结构:
form--has-error合理,但form--error-message-visible就越界了——错误提示是否显示,应由 DOM 存在与否或aria-live控制,不是样式层该管的事
最常被忽略的一点:BEM 的解耦能力,不来自符号本身,而来自对“什么才算一个功能单元”的持续追问。哪怕命名全对,如果 user-profile 实际包裹了地址编辑、订单历史、积分明细三个强耦合子模块,那它就不是真正的 Block —— 此时该拆,而不是靠 __ 和 -- 硬撑。


















