块名必须可独立复用,如.search-form;禁用.section、.container等视觉占位符类名;元素名不回溯语义,禁止嵌套拼接(如.card__card-title);修饰符须正交可枚举,避免描述性命名;BEM本质是所有权契约,明确归属、角色与状态。

块名必须可独立复用,不能是视觉容器
设计系统里最常踩的坑,就是把 .section、.container、.row 当成块。它们不是功能单元,只是布局占位符,一换栅格系统或响应式断点,所有依赖这些类的样式就全得重写。
真正该定义为块的,是能脱离上下文被任何页面直接引用的组件:比如 .button、.card、.form-field。判断标准很直接:这个类名删掉父级 HTML,它还能不能单独渲染出有意义的 UI?不能,说明它不该是块——可能只是某个块的元素,或者压根不该有类名。
- ✅ 正确:
.search-form(封装了输入框、按钮、清空图标,可插即用) - ❌ 错误:
.header-nav(没声明归属,.nav可能被其他模块复用,.header-nav又无法脱离 header 存在) - ⚠️ 高危:
.card-header(命名冗余,且暗示层级;应为.card__header或抽成独立块.header-section)
元素名不回溯语义,禁止嵌套式拼接
元素名只表达“它是什么”,不表达“它属于谁”。.card__title 是对的,.card__card-title 是错的——后缀里的 card- 不仅重复,还模糊了职责边界:如果将来要复用同一套标题样式到 .user-profile 里,你就得再写个 .user-profile__user-profile-title,明显不可持续。
设计系统中尤其要注意原子化收敛:如果 .button__icon 和 .modal__close-icon 样式完全一致,那它大概率不该是两个元素,而该是一个独立块 .icon-button 或 .icon,通过修饰符控制变体(.icon--close、.icon--menu)。
立即学习“前端免费学习笔记(深入)”;
- 元素只能出现在块的直接子节点上,HTML 中必须同时携带块类和元素类:
<div class="card"> <h3 class="card__title"> </h3> <li>禁止 <code>.block__elem1__elem2这种三层结构;需要深层结构时,应拆出新块:.form-field+.form-field__input+.form-field__icon - SCSS 中严格用
&__title,禁用.card .title这类后代选择器——它等于主动放弃 BEM 的作用域隔离能力 - 布尔型修饰符优先:
--disabled、--active、--focused - 键值型修饰符需限定取值范围:
--size-small、--theme-dark,避免--color-blue - 多个修饰符共存时,确保正交:
.button--primary--large合理,.button--primary--blue就冗余冲突 - 不要用修饰符替代 JS 状态管理:
--hidden必须由 JS 控制增删,而不是靠 CSS 强制隐藏所有内容
修饰符必须正交、可枚举,禁用描述性命名
设计系统要求状态可预测、可枚举。.button--red 是危险信号:品牌色一换,你得全局搜索替换;.button--large 是合理的,因为尺寸是有限集合(small / medium / large),且不与其他修饰符逻辑冲突。
修饰符只挂载在块或元素本身,不传递、不嵌套:.button--loading__text 是非法写法;正确是 .button--loading(影响整个块)或 .button__label--hidden(只影响 label 元素)。
CSS Modules 或组件库中,BEM 类名必须由组件内聚生成
React 项目里写 className={styles['button__icon']} 看似省事,实则破坏设计系统的演进弹性。一旦后续要把 icon 抽成独立 .icon 块,所有硬编码字符串的地方都会断。
安全做法是把块名作为组件常量收敛,所有派生类名基于它生成:
const BLOCK = 'button';
<button className={clsx(BLOCK, { [`${BLOCK}--loading`]: isLoading })}>
<span className={`${BLOCK}__label`} >{text}</span>
</button>
- 禁止手动拼接类名:
className={`button ${isActive ? 'button--active' : ''}`→ 改用clsx或classnames - 禁止跨块复用样式:即使
.input--small和.button--small视觉一致,也必须各自定义,避免耦合 - 变量命名也要 BEM 化:
$button-padding-vertical,而非笼统的$padding-sm
设计系统里最易被忽略的一点:BEM 不是命名长度竞赛,而是所有权契约。每个类名都在回答三个问题——它属于哪个块?它是块的哪部分?它当前什么状态?漏掉任一环,后续维护成本就会指数上升。


















