bem命名法通过block__element--modifier结构明确组件归属、层级与状态。如product-card__title--warning直指product-card块内标题的warning状态,避免泛化命名歧义,强制语义锚定与结构契约。

因为类名本身已携带「所属组件、结构角色、当前状态」三层信息,不依赖注释、不翻源码、不查文档就能看懂样式归属和用途。
类名直接暴露组件边界与层级关系
BEM 的 block__element--modifier 结构强制把语义锚定在具体组件上。比如 product-card__title--warning 一眼可知:这是 product-card 这个独立块里的标题元素,且处于 warning 状态。它不会被 user-card__title 干扰,也不随外层 font-size 漂移。
常见错误现象:.title 或 .header 这类泛化命名,你得点开 HTML 才能确认它属于哪个模块;而 BEM 类名扫一眼就还原出上下文。
-
card__header合法 —— 表明它是 card 块的直属头部 -
card-header非法 —— 丢失 block 上下文,退化为泛化选择器 -
card__header__title非法 —— 元素不允许嵌套,违反结构契约
Modifier 不是样式补丁,而是可验证的状态开关
修饰符(--)只回答“这个东西现在处于哪种可预期的状态”,不是对 CSS 属性的拼接。比如 button--disabled 是业务状态,button--red 是视觉描述——后者无法映射到交互逻辑,也难做自动化测试。
真实项目里最常漏写的是叠加规则说明:
-
button--primary和button--disabled可共存,但前提是 CSS 规则不依赖权重(即必须用.button--disabled { },而非.button.button--disabled { }) -
button--large和button--small互斥,文档里必须加⚠️警告:“二者不可同时使用,否则尺寸定义冲突” -
button__text--large非法 —— 修饰符不能降级到子元素内部
Element 不是 DOM 路径,而是功能角色声明
__ 表示“属于”,不是“在 HTML 里嵌套多深”。哪怕 card__title 在 DOM 中隔着三层 <div>,只要它是 card 的标题,就该叫这个。关键在于它是否承担那个结构角色。
<p>容易被忽略的硬约束:</p>
<ul><li>
<code>button__text 必须是 button 的**直接子节点**,中间不能隔 <span></span> 或 <div>
<li>设计稿中“带图标的按钮文字”,不能靠 <code>button__text__icon 解决,而应拆成并列元素:button__text + button__icon
icon)在按钮、导航、弹窗中都出现且行为一致,它就必须是独立 Block(icon),不能塞进 button__icon
真正让 UI 组件自成文档的,不是命名长度,而是每个连接符(-、__、--)都在传递不可绕过的契约信息:谁创建了它、它在结构里扮演什么、它此刻响应什么状态。漏掉任一环,下游开发者就会在真实项目里卡住两小时——而且查不出问题。











