BEM 命名规范
BEM 是一种通过 Block、Element、Modifier 命名约定模拟局部作用域的 CSS 组织方法,用来降低全局类名冲突和协作成本。
#type / concept
#status / growing
#tech / dev / frontend
#resource / css
#resource / bem
[!info] related notes
- 所属 MOC: CSS MOC
- 前置概念: CSS
- 并列概念: CSS Modules, CSS-in-JS, Sass / SCSS
- 易混淆概念: Scoped 样式的作用域原理
- 关系笔记: 前端样式方案演进与选型
BEM 命名规范
一句话定义
BEM 是一种 CSS 命名规范,通过 Block、Element、Modifier 把类名写成稳定的结构化名字,以在全局命名空间里人工制造“局部边界”。
核心机制 / 工作原理
BEM 的核心不是工具,而是约定。
它默认把一个 UI 单元拆成三层:
Block:独立存在的组件或模块Element:Block 内部组成部分Modifier:状态、尺寸、主题或变体
常见写法:
.card {}
.card__title {}
.card__footer {}
.card--featured {}
.card__title--muted {}
它试图解决的是全局 CSS 的命名冲突问题。
如果不用 BEM,项目里很容易同时出现很多 .title、.button、.content。
用了 BEM 后,类名会被拉回具体语境里,例如:
.product-card__title {}
.user-profile__title {}
.article-preview__title {}
这样虽然仍然是全局 CSS,但冲突概率会显著下降。
从本质上说,BEM 是在 CSS 缺少模块机制时,用命名约定补足模块边界。
最小例子 / 最小场景
<article class="card card--featured">
<h2 class="card__title">标题</h2>
<div class="card__content">内容</div>
<footer class="card__footer">尾部</footer>
</article>
.card {
padding: 16px;
border-radius: 8px;
}
.card__title {
font-size: 20px;
}
.card--featured {
border: 2px solid #1677ff;
}
阅读 .card__title 时,可以直接知道它属于 card,不会把它误判成全局公共类。
边界与易混淆点
- BEM 解决的是命名冲突和协作可读性,不是硬性的样式隔离。
- 如果有人直接写
.button {},工具并不会阻止全局污染,所以它依赖团队纪律和 code review。 - 类名可能变得很长,书写成本和视觉噪音会增加。
- BEM 和 Sass、CSS Modules 并不冲突。
- 在全局 CSS 时代,BEM 常作为主要隔离手段。
- 在 CSS Modules 时代,BEM 仍可作为组件内部的命名语言。
- BEM 更适合原生 CSS、传统多页面项目、或不想强依赖复杂样式运行时的团队。