bem不是字符串拼接规则,而是组件边界定义协议;写错block,后面全白搭。判断block或element的核心标准是:删掉父级类名后,该类能否独立复用、是否具备完整语义——能即为block,不能则必须作为element依附于block。

直接说结论:BEM 不是字符串拼接规则,而是组件边界定义协议;写错 Block,后面全白搭。
怎么判断一个类该叫 block 还是 element
核心就一条:删掉父级类名后,它还能不能独立复用、有没有完整语义?能,就是 block;不能,必须挂靠在 block 下,就是 element。
-
.search-form是 block —— 它在首页、弹窗、侧边栏都能原样复用,有自己完整的交互和样式逻辑 -
.search-form__input是 element —— 单独写class="search-form__input"没意义,没.search-form上下文,它连尺寸、边框、状态都定不下来 -
.logo通常该是 block —— 如果页头、页脚、404 页面都用同一套 logo 样式,说明它本身具备跨上下文复用能力,不该写成.header__logo - 常见错误:
.container、.section-2、.wrapper—— 这些只是布局占位符,没业务含义,一换结构就得重写 CSS
元素命名为什么不能带父级语义
因为 BEM 的类名要能“自解释”,.card__card-title 读起来像绕口令,且暴露了冗余信息:前面的 card 已经声明了归属,后面再重复,既增加长度,又提高维护成本。
- 正确写法:
.card__title、.user-card__avatar - 错误写法:
.card__card-title、.user-card__user-card-avatar - 更隐蔽的坑:
.button__icon和.modal__icon看似合理,但如果 icon 样式完全一致,其实该抽成独立 block.icon,否则改一个地方要同步多个类名
修饰符 --disabled 和 --primary 到底怎么选
修饰符名必须表达“意图”,而不是“实现”或“视觉”。--loading 是实现细节,--primary 是设计意图;前者随 JS 状态变,后者随产品规范变,稳定性差一个数量级。
- 推荐:
.button--primary、.button--large、.button__label--hidden - 禁止:
.button--loading(应由 JS 控制.button--busy+ 变量控制 loading 动画)、.button--blue(颜色应交由主题变量或--color-primary控制) - 多个修饰符可共存:
.button--primary--disabled合法,但前提是--primary和--disabled不互相覆盖关键属性(比如都设 background)
SCSS 里最容易破坏 BEM 封装的写法
所有含空格的选择器都会编译出后代关系,直接瓦解 BEM 的“单类名隔离”前提。浏览器匹配时会回溯 DOM 树,性能下降,还容易被意外嵌套结构漏掉样式。
- 安全写法:
.button {&__label { color: #333; }&--primary { background: #007bff; }} - 危险写法:
.button {&__content {&__icon { /* 编译出 .button__content .button__content__icon */ }}}—— 这不是 BEM,是嵌套灾难 - 验证方法:构建后执行
grep -r "\.[a-z]\+ \.[a-z]" dist/,命中即违规
真正难的从来不是记规则,而是每次加新类名前,停下来问一句:它到底属不属于这个块?能不能自己活?—— 这个判断一旦松动,BEM 就退化成带下划线的普通命名。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











