必须用stylelint-selector-bem-pattern在保存、提交、构建三环节强制拦截非法类名,否则三天内必现命名混乱;它通过结构锚点校验(如仅允许一个__或--)实现唯一可落地的BEM统一方案。

直接上结论:靠文档和口头约定无法统一 BEM,必须用 stylelint-selector-bem-pattern 在保存、提交、构建三个环节强制拦截非法类名——否则三天内就会出现 .btn__icon、.button__icon、.BtnIcon 并存。
为什么 stylelint-selector-bem-pattern 是唯一能落地的校验手段
人工 Review 永远追不上手滑速度;VS Code 插件只能提示,不能阻断;只有 stylelint-selector-bem-pattern 能在保存时直接报错,且支持 CI 级别拦截。
它不校验“好不好看”,只认结构锚点:
-
.card__title--large合法(有且仅有一个__或--,位置固定) -
.card-title--large、.card__title__sub、.modal .modal__content直接标红 -
componentName: '[a-z][a-zA-Z0-9]+'会拒绝UserCard、_header、card-1这类命名
如何配置 stylelint 实现三环节拦截
关键不是装插件,而是让规则匹配团队真实约束。以下配置已在多个中大型前端项目验证有效:
立即学习“前端免费学习笔记(深入)”;
module.exports = {
plugins: ['stylelint-selector-bem-pattern'],
rules: {
'plugin/selector-bem-pattern': {
componentName: '[a-z][a-zA-Z0-9]+',
styleType: 'bem'
}
}
};
配套动作必须跟上:
- VS Code 安装
BEM Helper插件,输入card回车自动展开card__title、card--hover等候选项 - CI 脚本中加入:
npx stylelint "**/*.{css,scss,less}" --max-warnings 0 - 禁止在 SCSS 中写
&__item { &__text { } }—— 这会生成后代选择器,破坏 BEM 平级原则
老项目怎么避免“统一标准=停工重写”
没人能说服 PM 推迟上线去改 200 个 .nav 类名。真正可行的是划清边界、守住新增、逐步收口:
- 所有新组件目录名即 Block 名:
/components/user-profile-card/→ CSS 文件必须叫user-profile-card.css,且只允许出现user-profile-card、user-profile-card__avatar、user-profile-card--compact - 高频冲突旧类(如全局
.table)不急于重命名,但加 wrapper 包一层:<div class="data-table">…</div>,后续扩展全走data-table__row、data-table--striped - 遗留 HTML 中的
class="card card--featured"必须确保 CSS 文件里同时存在.card和.card--featured规则——BEM 不允许修饰符脱离基础块
最常被忽略的一点:BEM 的约束力不在命名格式本身,而在它是否与目录结构、构建检查、Code Review 卡点形成闭环。漏掉任意一环,比如只配了保存时校验却没进 CI,或允许 JSX 里字符串拼接 className={`card ${isExpanded ? 'card--expanded' : ''}`},不出两周就会退回泛义命名状态。


















