bem官方命名未考虑业务语义与协作成本,导致命名与产品术语脱节、modifier状态不一致;需按业务模块定义block、用业务术语命名element、仅枚举稳定业务状态作modifier,并将bem规则嵌入设计交付流程。

为什么直接套用 BEM 官方命名会出问题
因为官方示例(如 block__element--modifier)没考虑业务语义和团队协作成本。比如你写 card__title--large,但产品文档里叫“主标题”,运营同学查不到;又或者 header__nav-item--active 在多个页面复用时,active 的判定逻辑不一致,导致样式错乱。
真正卡住落地的不是语法,而是命名背后的责任归属:谁定义 Block?谁决定 Element 是否可复用?Modifier 是视觉状态还是业务状态?
- Block 必须对应一个明确的业务模块(如
order-summary、product-filter),不能是纯布局容器(如container、wrap) - Element 名称优先用业务术语,而非视觉描述(用
order-summary__total-price,不用order-summary__big-number) - Modifier 只描述稳定、可枚举的业务状态(
order-summary__total-price--discounted✅;order-summary__total-price--highlighted❌——“高亮”是临时设计需求,不是业务状态)
怎么让设计师和前端对上同一个名字
关键不是开会对齐,而是把命名规则嵌入设计交付物。要求 UI 设计师在 Sketch/Figma 中图层名必须按 BEM 格式标注,例如:product-card → product-card__image → product-card__price--on-sale。前端切图时直接读图层名生成 CSS 类,省去二次翻译。
配套做两件事:
- 给设计工具装插件(如 Figma 的
css-class-name插件),自动校验图层名是否符合正则^[a-z][a-z0-9-]*(__[a-z][a-z0-9-]*)?(--([a-z][a-z0-9-]*))?$ - 在组件库文档中,每个组件的「使用说明」栏强制展示设计图层名与代码类名的映射表(不是只写代码)
- 禁止出现
u-text-center这类通用工具类——它绕过 BEM 语义,且设计师无法在设计稿里对应
如何处理跨业务线复用的组件命名冲突
当「购物车」和「收藏夹」都用到带删除按钮的商品项,不能简单共用 cart-item 或 favorite-item。BEM 不是解决复用,而是暴露复用风险。
正确做法是分三层命名:
- 基础结构层(Framework):用中性名,如
item+ 明确作用域前缀,cart-item和favorite-item各自独立,哪怕样式 90% 相同 - 视觉层(Skin):抽离颜色、间距等可覆盖变量,通过 CSS 自定义属性注入,不靠 Modifier 控制
- 行为层(Logic):删除操作的 class 必须带业务动词,
cart-item__remove-btn和favorite-item__remove-btn分开,避免 JS 绑定错事件
强行合并只会让 item__remove-btn--from-cart 这种怪异 Modifier 滋生,后期改一处,八处崩。
哪些地方最容易被忽略但致命
BEM 的坑不在写法,而在边界。最常被跳过的其实是「Block 的生命周期管理」:
- Block 必须有且仅有一个根节点,且该节点 class 必须与 Block 名完全一致(
<div class="payment-form"> ✅,<code><form class="payment-form"></form>❌——form是语义标签,不是 Block 容器) - 禁止跨 Block 使用 Element(
header__logo不能在footer里出现) - Modifier 必须依附于 Block 或 Element,不能单独存在(
--loading必须是button--loading,不能是loading独立类) - 所有类名必须能通过
grep -r "class.*[a-z]\+\(-\|__\|--\)[a-z]\+"在 HTML 中精准匹配,不允许动态拼接类名(如className={`${block}__${element}`})
这些约束看起来琐碎,但少一条,半年后就会出现 search-bar__input--dark-mode 和 search-input--dark 并存的混乱局面。











