bem的核心是让类名自带语义边界,不依赖dom层级,每个类名只描述单一职责,严格遵循block__element--modifier三段式结构,确保组件自治与可复用性。

为什么改HTML就崩样式?BEM不是加前缀那么简单
根本原因是传统CSS选择器过度依赖DOM层级,比如 .sidebar .item a:hover 这种写法,一旦把 a 换成 button,或者把 .item 提到 .sidebar 外层,样式立刻失效。BEM要解决的不是“怎么起名”,而是让每个类名自带语义边界,不靠父容器、不靠兄弟关系、不靠标签类型。
block__element--modifier 这套命名到底怎么落地
关键在「每个类名只描述一个职责」,且三段式结构必须严格对应组件层级。常见错误是把状态(如 is-active)和视觉变体(如 --large)混在同一层,或者给 __element 套嵌套选择器。
-
block必须是独立可复用的组件,比如header、card、form-field -
__element只能是block的直属子内容,不能跨级,例如card__title合法,card__title__icon违规(应拆成card__title-icon或新 block) -
--modifier只改变当前block或__element的表现,不触发布局重排,比如button--primary、nav-item--disabled - 绝对不用
div.card__title这类标签+类组合,所有样式只绑定类名
遇到嵌套组件时,BEM怎么避免类名爆炸
真实页面里常有 card 里套 list 再套 avatar,如果硬套三层BEM,类名会变成 card__content-list__item-avatar —— 这已经违背BEM初衷。正确做法是承认「组件自治」:每个子组件保持自己完整的BEM结构。
-
card内部用<div class="list"></div>,而不是<div class="card__list"></div> - 子组件的样式完全独立,
list的CSS文件不引用card的任何变量或选择器 - 若需微调(如
card里list的间距),用 modifier 控制:<div class="list list--in-card"></div>,而非加深选择器 - 工具链上可用 PostCSS 插件(如
postcss-bem)自动补全,但别依赖它生成嵌套类名
CSS-in-JS 或 Tailwind 下,BEM还有没有意义
有,但作用点变了。BEM在传统CSS里防样式污染,在现代方案里更多是统一团队对「什么算一个UI单元」的认知。
- 用
styled-components时,仍建议按Card.Title、Card.Content这种方式组织组件,本质就是 BEM 的block__element思维 - Tailwind 中避免写
flex flex-col gap-4 p-6 bg-white这种散装组合,而是封装成@layer components { .card { @apply flex flex-col gap-4 p-6 bg-white; } },这个.card就是 block - 最易被忽略的一点:BEM的 modifier 在原子化CSS里常被写成
class="card card--hoverable",但 Tailwind 用户容易直接加hover:shadow-md—— 这会让「可交互态」逻辑散落在模板里,后期想全局调整 hover 行为就很难
真正难的不是写对BEM语法,而是每次加一个新类名时,得停下来问一句:这个类名,脱离当前HTML结构后,是否还能被人一眼看懂它负责哪块视觉逻辑?
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











