靠命名空间(BEM)和自动化约束(stylelint、postcss-bem-linter、构建时校验)而非自觉,强制类名遵循block__element--modifier结构、禁用非BEM嵌套、规范引入顺序与文件边界。

怎么让多个团队改同一个CSS文件时不打架
靠命名空间和约束力,不是靠自觉。BEM强制把样式归属到具体模块,header__logo--dark 这种写法一眼就能看出它属于 header 模块、是 logo 元素、处于 dark 状态——没人能随便把它挪去用在弹窗里。
实操建议:
- 所有类名必须严格遵循
BEM三层结构:block__element--modifier,不允许嵌套层级(比如header__nav__item是错的,应拆成nav__item) - 模块级
block名必须对应组件名或页面区域名,如product-card、user-profile,避免泛化词如box、wrap - 团队共用的公共样式(如按钮、输入框)要抽成独立
base层,但依然走 BEM:用btn而不是button,因为后者容易和原生标签混淆,且不利于后续扩展状态类
如何避免 BEM 写着写着又变回“全局污染”
最常见的是开发者图省事,在 SCSS 中用 & 嵌套出非 BEM 结构,比如:
.card {
&__title { font-size: 18px; }
a { color: #333; } // ❌ 这里没加 __ 或 --,成了全局 a 标签样式
}
这种写法看着方便,上线后可能让整个站点的链接颜色突然变掉。
实操建议:
- 禁用任何不带 BEM 后缀的选择器嵌套,SCSS 中只允许
&__xxx和&--xxx,禁止& a、& > div这类写法 - 用 ESLint + stylelint 配置规则,检测
selector-max-universal和selector-no-qualifying-type,并启用postcss-bem-linter做构建时校验 - 每个 CSS 文件顶部加注释声明作用域,例如:
/* @scope product-list */,配合构建工具做作用域隔离(现代方案可用 CSS Modules,但需注意 SSR 和动态 class 拼接场景)
引入顺序搞错会导致 BEM 样式被意外覆盖
企业项目常把重置样式、基础组件、布局、页面级样式分文件引入,但只要 base.css 在 layout.css 后面加载,btn--primary 的背景色就可能被 layout 里一条宽泛的 .section .btn 干掉。
实操建议:
- 引入顺序必须是:重置 → 基础组件(
btn、input)→ 工具类(u-text-center)→ 布局(grid、header)→ 页面/模块(checkout-form) - 不要用
@import在 CSS 里跨文件引入,全部由构建工具(Webpack/Vite)统一控制依赖图;CSS 文件名按序号前缀,如00-reset.css、10-base.css,避免靠名字猜顺序 - 对关键修饰符(如
--disabled、--loading)加!important—— 不推荐,但比线上炸样式强;更稳妥的是用[class*="--disabled"]提高权重,而非依赖顺序
为什么有些团队用了 BEM 还是维护不动
问题不在规范本身,而在没配套约束机制。一个没配置 stylelint 的项目,BEM 很快退化成 userCard__title 和 user-card-title 并存;一个没拆分 CSS 文件边界的项目,profile.css 最后塞进 2000 行,连自己都找不到 profile__avatar 对应哪段逻辑。
真正卡住落地的点,其实是构建流程里缺了两样东西:一是自动检查类名是否符合正则 /^[a-z][a-zA-Z0-9]*(?:-[a-z][a-zA-Z0-9]*)*(?:__[a-z][a-zA-Z0-9]*(?:-[a-z][a-zA-Z0-9]*)*)?(?:--[a-z][a-zA-Z0-9]*(?:-[a-z][a-zA-Z0-9]*)*)?$/,二是每次提交强制生成 CSS 类名索引 JSON,供搜索和文档同步用。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











