bem中真正的“块”是独立、可复用、语义自洽的功能单元,如header、card;必须脱离上下文存在,命名小写短横线分隔,不带状态或位置描述,不嵌套其他block,禁用通用容器标签直接命名。

什么是BEM里真正的“块”(Block)
BEM的block不是HTML标签,也不是CSS选择器里的任意父容器,而是一个独立、可复用、语义自洽的功能单元。比如header、card、search-form——它必须能脱离上下文存在,不依赖外部样式或结构。
-
block名全部小写,用短横线分隔(user-avatar✅,UserAvatar❌) - 不带状态、不带位置描述(
top-banner❌,banner✅;active-tab❌,tab+tab--active✅) - 避免嵌套过深:一个
block内部不应再定义另一个block,否则说明职责没切分清楚
常见错误是把div、section这类通用容器直接当block命名(如section-1),结果导致样式无法复用、重构时牵一发而动全身。
修饰符(Modifier)该加在谁身上?
修饰符只作用于block或element本身,不能单独存在,也不能跨层级应用。比如button--primary是对button这个块的修饰;button<strong>text--large</strong>是对buttontext这个元素的修饰——但button--primary__text这种写法是错的,BEM不支持“修饰符+元素”的混合语法。
- 修饰符名建议用布尔型(
--disabled)或键值型(--size-large),避免歧义 - 同一
block上可以同时存在多个修饰符(button--primary--disabled),但需确保它们互不冲突 - 修饰符不改变结构,只改变外观或行为:不要用
--hidden来替代JS控制显隐,那属于逻辑层,应由类名+JS状态共同管理
容易踩的坑是把视觉差异当成修饰符滥用:比如仅因某处card背景色不同就加card--blue,而实际应归因于主题系统或CSS自定义属性,而非BEM层级。
Element命名何时该停?
element是block的组成部分,用双下划线连接(block__element)。关键判断标准是:它是否在语义和功能上完全依附于所属block?移除block后它还有独立意义吗?
-
menu__item✅(菜单项离开菜单无意义) -
form__submit-button✅(提交按钮属于表单上下文) -
header__logo✅(logo在此处是页头的一部分) -
logo❌(如果logo在多个地方复用且样式一致,它自己就是block)
性能影响常被忽略:过度拆分element会导致选择器过长(profile-card<strong>content</strong>title<strong>link</strong>),不仅难读,还可能触发浏览器CSS匹配回溯。BEM推荐深度最多两层:即blockelement,不鼓励block<strong>element</strong>subelement。
和CSS-in-JS或原子化CSS混用时怎么保持BEM价值?
BEM本质是命名约束,不是技术绑定。在使用styled-components或Tailwind时,仍可沿用BEM语义组织代码结构,只是实现方式不同。
- 在
styled-components中,可用as或className透传BEM类名,保证DOM结构清晰(<button classname="button button--secondary"></button>) - Tailwind项目里,不建议直接用
class="bg-blue-500 p-4 rounded"堆砌,而是封装成@layer components { .button { @apply bg-blue-500 p-4 rounded; } },再配合BEM命名约定 - 最容易被忽略的是:BEM类名必须出现在HTML/CSS输出中,不能只存在于JS变量里。否则调试时看不到语义,协作时无法对齐,DevTools里只剩一堆哈希类名
复杂点在于团队对“什么算一个block”的认知差异。有人觉得input-group是块,有人坚持input和label各自为块——这没有绝对答案,但必须文档化并统一落地。否则BEM会退化成一种徒增复杂度的命名幻觉。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











