bem真正起作用的是三层约束而非符号:block须为带业务含义的独立单元(如user-card),element仅属单一block且不可嵌套(user-card__avatar-icon正确,user-card__avatar__icon错误),modifier仅表达可预测状态(btn--disabled正确,btn--red错误)。

直接用 BEM 不会让 CSS 更语义化,关键在于你是否遵守它的三层约束:Block 必须是业务单元、Element 必须依附且不可嵌套、Modifier 必须表达状态而非样式细节。否则只是把类名变长,反而更难维护。
Block 名不能是 HTML 标签或布局词
比如写 .header__logo 看似合规,但 header 是泛标签名,不是独立可复用的组件。一旦页面出现 modal-header 或 email-header,header__logo 就会跨上下文污染样式。
- ✅ 正确做法:按业务功能命名 Block,如
.user-card、.search-form、.notification-banner - ❌ 错误做法:
.section、.container、.row—— 这些不带业务含义,加了__也救不回来 - 注意连字符规范:
.date-picker合法,.datepicker或.date_picker都违反约定
Element 命名必须绑定到单一 Block,且禁止嵌套
.user-card__avatar__icon 是典型错误 —— 它暗示了 DOM 层级,也违背了 “Element 只属于一个 Block” 的原则。BEM 不关心元素在 HTML 里嵌了几层,只关心语义归属。
- ✅ 正确写法:
.user-card__avatar-icon(把复合结构当一个元素)或拆出新 Block:.avatar-icon - ❌ 错误写法:
.user-card__avatar__image、.card-title(缺__,丢失 Block 上下文) - 元素名要语义化:
.btn__icon比.btn__el-1可读性强得多,重构时不用翻 JS 就能理解用途
Modifier 不是样式拼接器,而是状态开关
写 .btn--red 或 .btn--small 看似直观,实则把表现细节塞进了命名,导致后续改色或响应式调整时类名失效。BEM 的 Modifier 应该回答“它现在是什么状态”,而不是“它看起来什么样”。
- ✅ 合理修饰符:
.btn--disabled、.form-field--error、.card--featured - ❌ 常见陷阱:
.btn--large(尺寸应由@media控制)、.user-card--compact(这是响应式行为,不是固有状态) - 多个 Modifier 平级组合:
.btn--primary.btn--loading,不是.btn--primary-loading—— 后者隐含层级,人脑解析成本高
BEM 最容易被忽略的点,是把它当成字符串模板去套用。真正起作用的从来不是 __ 和 -- 这两个符号,而是你在写每个类名前,是否真想清楚了:这个东西能不能脱离当前页面单独存在?它有没有明确的业务职责?它的状态变化是不是可枚举、可预测的?
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











