用 stylelint 在 PR 阶段强制校验 BEM 命名,通过 stylelint-selector-bem-pattern 插件锁定 block 小写中划线、仅允许 __ 和 -- 结构、禁用复合选择器,CI 中禁用自动修复,人工聚焦处理泛义词、位置修饰符、弱元素名三类语义问题。

评审时一眼揪出非BEM类名,关键不是靠人眼扫,而是让 stylelint 在 PR 阶段就报错——没过校验的代码根本进不了主干。
为什么手动评审 BEM 几乎必然漏检
人对命名的判断带有模糊性:看到 .user-card-avatar 会犹豫它算不算 element,看到 .btn--sidebar 可能忽略“位置信息不该进 modifier”这条硬规则。更麻烦的是,评审者和提交者对“block 名是否泛义”理解不一致——.content 看似合理,但按规范必须拒绝;.dashboard-content 才合规。这种主观边界一旦没有工具卡死,就会在 Review 中变成无休止争论。
用 stylelint-selector-bem-pattern 锁死三类违规
这个插件不是装上就完事,得配准你团队的真实约束。以下配置能直接拦截最常踩的坑:
-
componentName: '^[a-z][a-zA-Z0-9]+(-[a-z][a-zA-Z0-9]*)*$':强制小写+中划线,堵死UserCard、user_card、_header -
styleType: 'bem':只允许block__element--modifier结构,.card .avatar或.card-avatar全部报错 - 配合
selector-max-compound-selectors: 1:禁用类型选择器,.card h3直接被拦,逼出.card__title
CI 脚本里必须加这行命令
光本地跑 stylelint 没用,PR 合并前必须卡住。CI 脚本中加入:
立即学习“前端免费学习笔记(深入)”;
npm run lint:css -- --fix=false
注意:--fix=false 是关键——禁止自动修复,避免机器改坏语义。报错必须由人确认、手动修正,否则合入即违规。
评审时只需盯住三处报错位置
真正要人工介入的,只剩 stylelint 报错的那几行。重点看:
- 报错类名是否含泛义词:
main、box、container→ 必须替换成带业务上下文的 block 名,如profile-layout - 修饰符是否描述状态:
btn--loading✅,btn--in-header❌(位置该由父容器类控制) - 元素名是否与 block 强相关:
modal__close-btn✅,modal__button❌(太泛,应为modal__close或modal__confirm)
复杂点在于,BEM 的“语义合理性”无法完全自动化——比如 user-card__avatar 合规,但 user-card__img 就弱了,这点只能靠人盯。别指望工具包圆所有事,但至少让它把机械错误全清掉。


















