BEM 的 block__element--modifier 结构不可随意更改,因其绑定 CSS 权重与可维护性,确保样式作用域清晰、避免覆盖;block 必须是独立功能单元,element 不可嵌套,modifier 仅描述状态或变体。

为什么 BEM 的 block__element--modifier 结构不能随便改
因为 CSS 选择器权重和可维护性直接绑定在这个结构上。一旦把 __ 换成 - 或者去掉双下划线,就等于放弃 BEM 的核心约束力——让样式作用域清晰、避免意外覆盖。
常见错误现象:.header-menu-item.active 看似合理,但和 .sidebar .menu-item.active 极易冲突;而 header__menu-item--active 从命名上就锁死了归属关系。
-
block必须是独立功能单元(如header、card),不能是语义化标签名(如div、section) -
__element不可嵌套:不允许出现header__logo__icon,应拆成header__logo和logo__icon -
--modifier只能描述状态或变体,不能带具体值,比如用button--primary,别写button--width-200px
如何把现有项目渐进式迁移到 BEM
硬推全量重命名会卡在协作和回归测试上。关键是先守住新增代码,再用工具辅助旧代码收敛。
使用场景:老项目加新模块、组件库升级、多人并行开发中统一风格。
- 用 ESLint 插件
stylelint-selector-bem-pattern在 CI 中拦截非 BEM 命名的 CSS 类 - VS Code 安装
Auto Rename Tag+ 自定义 snippet,输入bem直出block__element--modifier模板 - 对已有类名做最小改动:把
user-list-item改为user-list__item,不碰逻辑,只调样式层
block__element--modifier 在 CSS-in-JS 和 Tailwind 中怎么落地
BEM 是思想,不是 CSS 文件格式。它在不同技术栈里表达方式不同,但约束目标一致:样式归属明确、无隐式继承、可预测。
参数差异:
- 在 styled-components 中,用
const Button = styled.button.attrs({ className: 'button' })保证根节点有block类,内部元素靠 props 控制--modifier - Tailwind 不鼓励写 class 名,但可用
@layer components封装 BEM 风格的原子组合,例如@apply button__text--large对应预设样式 - Vue SFC 的
无法替代 BEM,scoped 只解决全局污染,不解决组件内层级混乱
哪些情况不适合强推 BEM
不是所有 CSS 场景都适合套用 BEM。过度标准化反而增加理解成本,尤其在快速验证、原型或极简 UI 中。
性能 / 兼容性影响:BEM 类名普遍偏长,gzip 后影响微乎其微,但开发者阅读负担真实存在。
- 工具类优先的项目(如纯 Tailwind 项目):BEM 会和 utility-first 思路打架
- 设计系统底层原子组件(
Icon、Spinner):用icon、spinner单一名字更自然,加icon--filled反而冗余 - 服务端渲染且 CSS 提取为独立文件的场景:BEM 对 SSR 无额外收益,重点应在 critical CSS 切分
真正难的不是写对一个类名,而是团队在「什么算一个 block」「element 边界在哪」这些地方达成一致。没共识时,强行统一命名只会催生更多例外规则。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











