BEM 的核心是用命名强制划分作用域,通过 block__element--modifier 结构实现语义化、低耦合、高可维护的 CSS 组织方式。

为什么直接写 .button 会让人改着改着就崩溃
因为样式污染和定位失控不是“会不会发生”的问题,而是“什么时候爆发”的问题。BEM 的核心不是加一堆下划线,是用命名强制划分作用域——block__element--modifier 这种结构让每个类名自带上下文,浏览器不关心,但人一眼能判断:这个 header__logo--large 只属于 header 块,不会意外影响 footer 里的同名元素。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 块名必须语义化且唯一,避免
.card这种泛称,优先用业务场景定名,比如.product-card或.user-profile-card - 元素名只描述角色,不描述样式,写
product-card__price,别写product-card__red-text - 修饰符必须是布尔态或有限枚举,
product-card--featured✅,product-card--bg-blue❌(颜色应抽成设计系统变量,不在 BEM 层体现)
如何让 BEM 真正跑起来,而不是变成命名负担
BEM 不是手写一串下划线,它依赖工具链配合。手动拼接 modal__content--scrollable 容易漏字符、大小写错、层级混乱——尤其嵌套深时,form__field-group__input--error 这种写法已经违背 BEM 原则(元素不能嵌套元素)。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 用 PostCSS 插件
postcss-bem或预处理器的嵌套语法(如 Sass 的&__content),把视觉层级转为代码层级,避免手误 - 组件级 CSS 模块化优先于全局 BEM,React/Vue 中直接用
className={styles['button--primary']}配合css-modules,比纯 class 字符串更安全 - 禁止跨块组合类名,
<div class="button product-card__cta"></div>是反模式——按钮逻辑应收敛在button块内,product-card__cta应继承或透传button的基础样式
遇到 Specificity 爆炸时,BEM 怎么救你
传统写法里,#sidebar .list .item a:hover 和 .theme-dark .nav a 打起架来谁权重高?很难肉眼算清。BEM 类名天然扁平:sidebar__list-item-link 一个类名搞定,权重恒为 0,1,0,0,彻底避开 !important 和无休止的父选择器叠加。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 禁用 ID 选择器、标签选择器、属性选择器(如
[type="submit"])参与样式定义,BEM 下所有样式必须由类名驱动 - 伪类状态统一挂载在块或元素上,写
button--disabled,而不是button:disabled——后者无法被 JS 切换,且破坏 BEM 的状态显式性 - 媒体查询内保持 BEM 结构,
@media (min-width: 768px) { .header__nav--mobile { display: none; } },别为了“省事”写成.header .nav-mobile
从老项目迁移 BEM 最容易卡在哪
不是命名不会写,是旧代码里大量依赖“就近修改”和“覆盖优先”的隐式逻辑。把 .btn-primary 改成 button--primary 后,JS 里 document.querySelector('.btn-primary') 就失效;Webpack 的 mini-css-extract-plugin 如果没配好局部作用域,CSS 抽离后仍可能全局污染。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- JS 中所有 DOM 查询必须同步更新,推荐用
data-*属性做行为钩子,比如data-js="toggle-menu",彻底解耦样式名和行为名 - 启用 CSS Modules 或
scoped(Vue)/cssprop(Emotion)作为过渡手段,逐步替换全局 class,别指望一次重命名解决所有问题 - 保留旧类名做兼容层,用
.btn-primary { @extend .button--primary; }(Sass)或 CSS 自定义属性桥接,给业务逻辑留出改造窗口期
BEM 的复杂点从来不在命名规则本身,而在它逼你直面组件边界是否真实存在——如果一个 card 里要塞进表格、表单、弹窗,那问题不是怎么命名,而是这个 card 早该拆了。


















