Block名必须带业务语义且全局唯一,如user-card;禁止用结构名、样式名或位置名;Block需独立可复用,职责单一,类名须静态声明并显式写出。

Block 名不能是 HTML 标签名或视觉容器
直接用 div、section、header 作 Block 名,等于放弃样式隔离。比如写 header__logo,结果页脚也用 header__logo —— 这不是复用,是命名污染。
常见错误还包括:left-sidebar、section-2、container。它们描述位置或结构,不是功能单元,没法独立交付、没法跨页面复用。
- 合格的 Block 名必须带业务语义:如
user-card(用户信息卡片)、search-form(搜索表单)、nav-menu(主导航菜单) - React/Vue 组件名小写中划线化就是天然 Block 名:
UserCard.vue→user-card - 全局唯一性要靠前缀兜底,避免和第三方库冲突,比如
nc-button比button更安全
Block 必须能独立存在且可复用
一个 Block 不是“这个 div 里所有东西”,而是“这个功能模块能不能单独抽出来用”。如果某块内容只在首页出现、逻辑耦合严重、换个页面就失效,它大概率不是 Block,只是临时分组。
典型反例:list-page__item —— 它暗示“这是列表页的子项”,但实际 document-item 在详情页、搜索页、侧边栏都可能复用,它早该是独立 Block。
立即学习“前端免费学习笔记(深入)”;
- 判断标准:删掉它,页面其他部分是否仍能正常工作?能否作为独立组件被其他项目引入?
- Block 的职责要单一:一个
product-card只管商品展示,不掺杂购物车操作逻辑;购物车按钮应是另一个 Block 或通过product-card__action表达组合关系 - 不要为状态或样式起 Block 名:
big-card、red-banner都错——尺寸和颜色会变,“商品卡片”不会
Block 名必须静态声明,禁止 JS 拼接
类名拼接(如 className={`${block}__${element}`})破坏 BEM 的可预测性和工具链支持。CSS-in-JS 或构建时提取类名的工具(如 PostCSS BEM 插件)依赖静态字符串匹配。
更隐蔽的问题是:拼接导致审查元素时看不到完整类名,调试困难;同时 SCSS 中 &__title 这类嵌套也失效。
- 推荐在组件顶层定义常量:
const BLOCK = 'product-card',后续所有类名基于它生成 - HTML 中必须显式写出完整类名:
class="product-card__title",不能省略或动态构造 - 禁止使用后代选择器替代 BEM:
.product-card h2是反模式,它绕过了 Block 作用域,增加权重且无法复用
修饰符和元素名不能泄露 Block 的实现细节
Block 名一旦定下,Element 和 Modifier 就得严格依附它。如果 Block 名本身含位置、样式或临时标识(如 v2、new),整个链条都会失稳。
例如 sidebar-btn 作为 Block,会导致 sidebar-btn__icon 绑死 sidebar 上下文;而换成 btn 后,btn__icon 才真正可复用。
- Modifier 必须表达稳定状态:
btn--loading✅,btn--red❌;menu--horizontal✅,menu--wide❌ - Element 名不含 Block 语义:
card__title✅,card__card-title❌;btn__text✅,btn__btn-text❌ - 同一个 Element 在不同 Block 中出现,应保持名称一致:按钮文字在
user-card和product-card里都叫card__title,而不是各自造轮子


















