bem 类名需脱离 html 结构独立存在,如 .user-card__avatar 可复用,而 .card__title 依赖父级、.card__header__title 嵌套违规、.is-active 缺乏上下文;修饰符应作用于 block 根而非元素。

为什么 .card .title 一复制就失效
浏览器匹配选择器是从右往左的:.card .title 实际在找「所有带 title 类、且父级有 card」的元素。一旦新页面结构是 <section class="product-card"><h3 class="title"></h3></section>,.title 就脱离了 .card 包裹,样式立刻断掉。
更隐蔽的问题是继承污染:外层 font-size: 0.875rem 会通过 DOM 树影响 .title,但你根本没在规则里声明它,改起来像捉迷藏。
.card__title 不依赖父容器是否存在,只要 HTML 里写了这个类,样式就生效。它不靠层级“推导”作用域,而是用命名显式声明:“我只属于 .card”。
如何写出真正可复用的 BEM 类名
关键不是字符长度,而是能否脱离当前 HTML 结构独立存在、被理解、被迁移。
-
.user-card__avatar✅ ——avatar是user-card的视觉组成部分,挪到新页面仍能识别上下文 -
.user-card__avatar--round✅ —— 状态修饰符依附明确,不单独使用 -
.user-card__header__title❌ —— 元素不能嵌套;__header本身已是一个子结构,应拆为独立 block -
.is-active或.active❌ —— 纯状态类无上下文,不知道它属于谁;应写作.user-card--selected或.button--disabled -
.search-input✅ —— 功能命名优于位置命名(如.header__search),方便在弹窗、侧边栏等多处复用
现有项目补 BEM 容易踩的三个坑
别一上来就重命名全部 class,容易翻车。重点盯住高频、跨业务复用的模块(如表单控件、卡片、弹窗)。
常见错误现象:
- 只改子元素 class,漏掉块根:写了
.card__title却保留旧的.title,导致样式残留或冲突 - 修饰符挂错位置:给
.card__title加--large,而不是统一由.card--large控制整体缩放——这破坏了 modifier 应作用于 block 根的原则 - 和第三方组件库硬刚:直接覆盖
.el-button类名。结果升级 Ant Design 后样式崩,还污染全局。稳妥做法是封装 wrapper:<div class="my-button"><el-button class="my-button__inner">提交</el-button></div>,只对.my-button和.my-button__inner写样式
Sass 中写 BEM 别让嵌套反向破坏扁平性
Sass 的 & 嵌套本身不坏,但容易写出违反 BEM 原则的 CSS。
比如这样写就错了:
.card {
&__title {
&--large { font-size: 1.5rem; }
}
}
产出的是 .card__title--large,看似规范,实则语义断裂——title 是 card 的元素,large 是 card 的状态,不该绑定到 title 上。
正确方式是让修饰符只作用于 block 根:
.card {
&--large {
font-size: 1.5rem;
}
&__title {}
}
这样 .card--large .card__title 才能自然继承缩放,也符合 BEM 的层级约束。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











