BEM命名应绑定业务语义而非视觉或位置,block需可独立复用,__仅用于element,_仅用于modifier,嵌套超三层需重构,工具校验防语义滑坡。

为什么.btn-primary比.blue-button更可靠
因为前者绑定的是组件角色,后者绑定的是视觉状态——一旦设计改用紫色主按钮,.blue-button就成了一句谎话,而.btn-primary依然成立。BEM的block名(如btn)必须对应一个可独立存在的UI单元,不是“左上角那个灰色小图标”,而是“导航菜单中的触发按钮”。
- 命名必须能回答“这个东西在业务里叫什么”,而不是“它现在长什么样”
- 避免带位置信息的词:
.header-left、.sidebar-item-2都是危险信号 - 如果团队里有人对某个
block名有歧义,说明它还没达到语义闭环,得重聊
__和_到底什么时候用,别混成一团
__(双下划线)只用于element,表示块内部的子节点;_(单下划线)只用于modifier,表示块或元素的状态变体。错用会导致样式不可预测——比如把.btn_size-large写成.btn__size-large,CSS选择器就完全失效了。
-
.card__title✅ 卡片里的标题(element) -
.card_is-collapsed✅ 卡片的折叠状态(modifier) -
.card__title_is-highlighted✅ 标题的高亮状态(modifier on element) -
.card_title-large❌ 缺少分隔符,语义断裂 -
.card--hover❌ 混入其他命名规范,BEM不认
嵌套三层以上?大概率是block拆错了
BEM不反对嵌套,但反对“为了嵌套而嵌套”。出现.page__section__list__item__link这种写法,通常意味着你把本该是独立block的list和item强行降级成了element。真正的block应该能脱离上下文被复用。
- 检查是否能单独抽出来:把
.list整个复制到另一个页面,它是否仍能正常渲染、有明确用途?能 → 应该是listblock - 避免“伪嵌套”:
.header__nav__item__icon中nav和item都该是独立 block - 工具提示类组件(如
tooltip)哪怕只在按钮里用,也该是 block,不是.btn__tooltip
用postcss-bem-linter跑一遍,比人工 Review 管用十倍
人眼容易忽略命名断层,比如.form__input_required看起来没问题,但required其实是表单域的校验状态,属于form层级的 modifier,不该挂在input上——正确应是.form_is-required .form__input。这类逻辑偏差,靠肉眼很难持续守住。
立即学习“前端免费学习笔记(深入)”;
- 装插件:
npm install postcss-bem-linter --save-dev - 加到 PostCSS 配置里,启用
component模式(比strict更贴合真实项目) - CI 里跑检查,报错直接卡住合并 —— 不是为炫技,是防止语义滑坡从第一行就开始
真正难的从来不是记住规则,而是每次加新 class 前,愿意花三秒问一句:“这个东西,在产品文档里怎么叫?”


















