BEM通过类名嵌入块、元素、状态信息实现高可读性与可维护性:user-card__avatar--loading明确归属、功能与状态;文件名与块名强制对应便于定位;工具链实时校验命名规范,守住协作底线。

因为BEM把“这个样式属于谁、是什么、当前什么状态”三个问题直接塞进类名里,新人打开文件或审查元素,30秒内就能定位作用域、理解意图、知道怎么改——不需要翻HTML、不靠猜、不问人。
看到 user-card__avatar--loading 就能立刻判断三件事
新人在 DevTools 里点开一个元素,类名不是 .avatar 或 .loading 这种裸名,而是带完整上下文的 user-card__avatar--loading:
-
user-card是块名 → 它属于“用户资料卡片”这个独立功能单元,不是通用头像组件 -
__avatar是元素名 → 它是 user-card 内部的头像部分,不能脱离块单独复用 -
--loading是修饰符 → 当前处于“加载中”状态,由 JS 控制切换,不是视觉尺寸或颜色
这种命名天然排除了歧义:不会误以为 --loading 是给按钮或弹窗用的,也不会把 user-card__avatar 当成全局头像样式去改。
文件名和块名强制一一对应,IDE 搜索即得全部逻辑
老项目常把按钮样式散落在 base.css、ui-kit.css、profile-page.css 里,新人最怕“这个按钮样式到底在哪改?”
立即学习“前端免费学习笔记(深入)”;
- BEM 要求每个块独占一个文件:
button.css里只允许出现button、button__icon、button--primary等类名 - 新人在 VS Code 里按
button.css搜索,ctrl+click 就跳转到完整样式定义,不用 grep 全局 - 删组件时直接删
user-card.css文件即可,不会有漏掉的“幽灵样式”藏在别的文件里
文件开头还带标准化注释,比如:
/*<br>* @block user-card<br>* @description 用户资料卡片,支持头像尺寸/信息折叠/操作按钮显隐<br>* @modifiers: --compact, --with-actions, --loading<br>*/
新人打开就清楚:哪些状态是设计认可的,哪些类名可以直接复用。
工具链能在保存时拦住常见手滑错误
光靠文档和培训拦不住拼写错误,必须让违规在编辑器里实时报错:
- 用
stylelint-selector-bem-pattern插件,配置{ "componentName": "[a-z][a-zA-Z0-9]+", "styleType": "bem" },自动拦截.header .logo或btn-primary这类非 BEM 写法 - VS Code 安装 “BEM Helper”,输入
user-card回车,自动补全user-card__和user-card--,避免漏写前缀 - CI 流程中跑
npx stylelint "**/*.{css,scss}",失败即阻断合并,防止伪 BEM(如 HTML 写class="card card--featured",但 CSS 里只定义了.card--featured)
这些不是锦上添花,而是守住底线:只要文件存在、工具开着,新人写的类名就不可能脱离块上下文。
真正容易被忽略的是——BEM 不解决层叠顺序问题。user-card__title--large 和 user-card__title--small 谁生效,取决于它们在 CSS 文件里的书写顺序,而不是 HTML 中 class 的先后。这点必须靠构建时确定引入顺序来管住,不能指望命名本身。


















