bem规范通过将作用域、元素角色和状态硬编码进类名(如.user-card__avatar--loading),使新人1秒定位样式归属,无需查html/js,大幅降低溯源时间。

掌握 CSS BEM 规范本身不降低代码量,但能直接砍掉新人 60% 以上的「类名溯源时间」——看到 .user-card__avatar--loading,不用打开 HTML、不查 JS、不翻组件 props,就能 1 秒定位作用域、元素角色和当前状态。
看到类名就知道它属于哪个模块
BEM 把归属信息硬编码进字符串里,而不是藏在 DOM 层级或文件路径中。传统写法如 .title 或 .btn 没有上下文,新人得靠猜或全局搜索;而 .product-card__title 一目了然:这是 product-card 模块里的 title 元素。
- IDE 里 Ctrl+Click
product-card__title,直接跳转到product-card.css,不会误入header.css或base.css - 搜索
user-card__,结果只返回 user-card 相关样式,不会混入order-card__或card__ - 禁止跨文件定义同一 Block,删掉
user-card.css就等于删干净所有相关样式,无残留风险
不用看 HTML 结构就能判断样式是否生效
BEM 类名不依赖父容器、不依赖标签类型、不依赖嵌套深度。这意味着即使把 <div class="user-card__avatar"> 单独复制到新页面,样式依然有效——它只认这个字符串,不关心它在哪。
<ul>
<li>避免传统写法 <code>.user-card .avatar 的静默失效:DOM 一改(比如去掉 .user-card 外层容器),样式立刻消失,控制台还不报错
button、p)和组合选择器(如 .card > .title),所有样式都靠单类名触发user-card__avatar 匹配的,而不是一堆带空格的选择器Modifier 命名强制绑定可预测状态
修饰符不是尺寸或颜色开关,而是业务上可枚举、可触发的状态。这大幅减少新人对“什么时候该加这个类”的困惑。
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
- 正确:
.button--disabled(JS 调用el.classList.add('button--disabled')有明确触发逻辑) - 错误:
.button--small(“小”是视觉描述,响应式下可能变大;没人知道它该在什么条件下出现) - 拼写断裂点常被忽略:
button--primary button--loading是合法叠加,button--primary--loading是非法双连字符,CI 必须用stylelint-selector-bem-pattern拦住
JS 动态拼类时最容易漏掉的三个硬约束
React/Vue 中手写 className 是新人高频出错区,BEM 的结构要求在这里变成显性检查项。
- 漏写 Block 前缀:
className={isFeatured ? 'featured' : ''}❌ → 应为product-card--featured - 连字符位置错:
card__title--large❌(Element 后不能接--)→ 正确是card--large card__title - 大小写/分隔符不一致:
UserCard__header和user-card__header在 Linux 构建环境是两个不同类名,样式丢失且无报错
真正难的不是记住 __ 和 --,而是每次写 class 前下意识问一句:“这个东西,离开当前 Block 还能不能单独存在?”——这个问题的答案,决定了类名是真 BEM,还是徒有其表的长字符串。










