必须用构建链路+工具校验+作用域隔离三者组合落地CSS命名冲突问题;BEM需block名带业务语义、工具强制校验、目录对齐,否则仍会冲突;CSS Modules仅兜底,不能替代规范命名。

多团队协同开发时,CSS命名与引入冲突不是“会不会发生”的问题,而是“什么时候爆发”的问题。直接结论:靠人盯人、口头约定或文档说明无法根治,必须用构建链路+工具校验+作用域隔离三者组合落地。
为什么
多个团队各自维护组件库或业务模块时,.button这种泛义名在不同 CSS 文件中重复定义是常态。浏览器不关心谁写的,只按 <link> 顺序 + specificity + !important 决定最终样式。你改了 Button.css,但页面没变,大概率是第三方 UI 库的 .el-button { color: red !important; } 挡住了。
- 用 DevTools 的 Styles 面板点开每条规则,看哪些被划掉、为什么被划掉(灰色文字 + “invalid” 提示)
- 禁止在业务组件里写
!important—— 它会破坏 BEM 的层级预期,让button--large无法覆盖button - 全局 CSS 文件(如
base.css)只放html、body、h1等基础重置,禁用任何带__或--的类名
怎样让BEM真正起效而不是徒有其表
BEM 不是改个名字就完事。它需要 block 名带业务语义、工具链强制校验、文件结构对齐。否则 .header__logo--dark 和另一个团队的 .header__logo--dark 依然可能打架。
- Block 名必须唯一且带上下文,比如
user-profile而非profile,避免和product-profile冲突 - 禁用
global、base、layout这类泛义词当 block 名 —— 它们注定在第 3 个迭代变成命名黑洞 - 用
stylelint-selector-bem-pattern配置componentName白名单,限定 block 只能是['button', 'card', 'form']等预设值 - 目录名 = Block 名:
search-form/下只允许出现.search-form、.search-form__input、.search-form--compact
CSS Modules 是兜底方案,但不能替代命名规范
CSS Modules 生成哈希类名(如 Button_module__button___aBc12)确实能隔离作用域,但它不解决命名懒惰问题。如果两个团队都写了 .btn,模块化后变成 Btn_module__btn___xYz34 和 Form_module__btn___mNo56,调试时仍难定位语义。
立即学习“前端免费学习笔记(深入)”;
- 开启
modules: { mode: 'local' },确保import styles from './Button.module.css'中的styles.button编译后自动加哈希 - 仍需规范命名:避免
.btn和.button在不同模块里同时出现 —— 哈希只是兜底,不是命名偷懒的理由 - 全局类(如第三方库的
.el-button)必须用:global(.el-button)显式声明,否则会被模块化 - Vue/React 中别硬拼字符串:
class="card__body"或el.classList.add('card__body'),重构块名时极易漏改
老项目怎么落地而不卡住开发节奏
全量重命名等于停工一周。真正可行的是守住新增、收敛旧边界、不推倒重来。
- 所有新组件(弹窗、筛选栏、用户卡片)100% BEM,目录即 block 名:
modal/下只允许.modal、.modal__header、.modal--fullscreen - 高频冲突类(如遗留的
.table)先用 wrapper 包一层:<div class="data-table">…</div>,后续扩展全走data-table__row - 遗留
.nav类不急于改,但新增子项必须写成header-nav__item,逐步收口 - CI 中加
npx stylelint "**/*.{css,scss}",失败即阻断合并 —— 工具比人更守规矩
最常被忽略的一点:BEM 的 __ 和 -- 不是风格偏好,是工具链识别边界的语法锚点。写成 .menu_item 或 .button-disabled,PostCSS 插件、VS Code 补全、甚至某些构建时 Scope 提取工具就无法识别这是元素还是修饰符。一旦失去工具支持,BEM 就退化成一种徒增打字量的命名习惯。


















