bem本质是建立“类名即契约”的直觉:每个类名须明确回答“这是谁的、是什么、什么状态”;block需独立存在且可复用,element依赖父级,modifier须表意图而非实现。

掌握BEM不是背规则,而是建立「类名即契约」的直觉:每个类名必须能回答“这是谁的、是什么、现在什么状态”——答不全,就大概率写错了。
怎么一眼判断该起 block 还是 element
看它能不能脱离上下文独立存在、有没有复用价值。比如 .search-form 是 block,因为它可能出现在首页、弹窗、侧边栏;而 .search-form__input 离开 .search-form 就语义断裂、样式失效,只能是 element。
- 常见错误:把
.section-2、.wrapper当作 block —— 它们只是临时布局占位符,没业务含义,无法跨页面复用 - 合格 block 名必须是「名词 + 角色/功能」组合,如
.user-card、.notification-banner - element 名称里不带父级语义:
.card__title正确,.card__card-title冗余
modifier 为什么不能写 --loading 而要写 --primary
--loading 揭露实现细节,和 JS 状态强耦合;--primary 表达意图,和业务逻辑对齐。设计师换主题时,改一个变量就能让所有 .button--primary 同步变色;但若满屏都是 .button--loading,就得手动搜替换,还容易漏掉。
- 禁止用视觉描述:
--blue、--small、--left - 禁止用临时标签:
--v2、--new、--temp - 允许修饰 element,但仅限影响自身:
.search-form__submit--disabled可以,.search-form__submit--in-modal不行(牵扯容器逻辑)
SCSS 里嵌套怎么写才不破坏 BEM 封装性
BEM 的 CSS 输出必须是扁平类名,不允许出现空格连接的选择器。Sass 中只允许 &__ 和 &-- 这两种单层嵌套形式,其他都危险。
- 正确:
.search-form {<br> &__input { font-size: 1rem; }<br> &--compact { padding: 0.5rem; }<br>} - 错误:
.card {<br> &__content {<br> &__icon { /* 编译出 .card__content .card__content__icon */ }<br> }<br>}—— 这违反 element 不可嵌套原则 - 禁用
@extend跨 block 共享样式:哪怕.button--small和.input--small样式相同,也必须各自定义
重构旧项目时最容易踩的三个坑
老代码里直接搜 .btn 全局替换为 .button__text?别急。真实项目里,JS 可能正用 document.querySelector('.btn') 绑定事件,HTML 里也可能混着 class="btn btn-red" 这种写法。
- 先筛三类高危类名:
.btn、.card、.nav这类泛化命名;高频修改文件里的混杂类(如.sidebar);JS 硬编码依赖的类 - HTML 结构不动,只加归属:原
class="form"改成class="login-form",<input>加class="login-form__input" - 工具类(如
.clearfix、.hidden)统一迁到u-clearfix、u-hidden前缀下,和 BEM 业务类物理隔离
真正难的不是记住双下划线和双短横,而是每次写类名前,下意识问一句:“这个东西,离开当前上下文还能不能活?”——答案决定它是 block 还是 element,也决定了整个组件的可维护边界。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











