BEM是多人协作下防止样式雪崩的底线契约,因.btn类名无归属、无责任人、无法评估影响范围,而user-profile__submit-btn--disabled自带模块、元素与状态上下文,实现语义化协作与精准定位。

不是“最佳实践”这个说法本身站得住,而是当项目跨过三人、两个子应用、三套构建流程之后,.btn 这种类名在 CSS 里就等于没定义——它不指代任何具体模块、不绑定任何责任人、无法判断删改影响范围。BEM 不是锦上添花的命名风格,是多人协作下防止样式雪崩的底线契约。
为什么 .btn 在百人团队里查不到归属
浏览器不关心你写的是按钮还是轮播控制点,只认字符串 .btn。它可能来自 reset.css、UI 库、Billing 模块的 button.scss,甚至某人临时加的 div.btn。没有上下文,.btn { padding: 4px } 就是颗定时炸弹:谁最后加载,谁生效;谁先写,谁被覆盖。
-
user-profile__submit-btn--disabled一眼可知:属于用户档案模块、是提交按钮、当前禁用态 - 搜索
user-profile__能直接定位到唯一 SCSS 文件和组件目录 - VS Code 插件输入
user-profile__回车,自动补全所有合法元素名,不靠记忆
SCSS 嵌套怎么不产出带空格的选择器
很多人写 .btn { &__icon { } &--loading { } } 就以为合规,但一不小心就漏出全局规则:
-
.btn { a { color: blue; } }→ 编译后是全局a选择器,和 BEM 无关 -
.btn { & > span { } }→ 生成.btn > span,依赖 DOM 结构,微前端里父容器一换就失效 - 真正安全的只有两种嵌套:
&__element和&--modifier - CI 阶段必须用
stylelint-selector-bem-pattern拦截,不能靠人眼检查
修饰符(Modifier)为什么不能叫 btn--width-200px
把具体值塞进类名,等于把 CSS 变量硬编码进 HTML,响应式、主题切换、设计 token 替换全失效:
立即学习“前端免费学习笔记(深入)”;
-
btn--primary✅:由设计系统--color-brand-primary驱动,换主题只需改变量 -
btn--loading✅:状态可组合,能和--primary共存 -
btn--bg-blue-500❌:换色得全局搜索替换,且无法适配暗色模式 -
btn--primary--large--disabled❌:连缀式命名无法单独覆盖,JS 控制也难收敛
为什么 DevTools 的 Computed Styles 面板比文档更可靠
规范写得再细,最终生效的是浏览器里看到的选择器。打开 Elements → Computed → Styles,直接看:
- 有没有空格?有空格就是
.card .card__title,性能隐患 - 有没有意外混入的
div或[data-foo]?说明写了& div或&[data-foo] - 构建后用
grep -r "\.[a-z]\+ \.[a-z]" dist/能快速揪出残留的空格选择器 - 真正难的不是写出
block__element--modifier,而是每次加--时都问一句:这个状态是否可枚举、可复用、不带硬编码值?


















