bem选择器权重恒为0-1-0,因其强制使用单类名选择器,禁止后代/子代选择器及标签限定,仅允许修饰符连写(如.button--hovered);一旦出现嵌套或标签组合,权重即突破0-1-0,导致控制失效。

BEM 不是“降低”权重,而是让所有有效选择器的权重恒定为 0-1-0,彻底消除权重竞争场景——只要你严格按规则写,就没人能靠多套一层父类或加个标签名来“压过”你。
为什么 BEM 选择器权重一定是 0-1-0
浏览器计算 specificity 时,只看选择器中各类符号的数量:.button__icon--loading 含 1 个 class,权重就是 0-1-0;而 .modal .button 是 2 个 class,权重变成 0-2-0,已破防。
- 所有合法 BEM 选择器必须是单个类名,禁止空格、
>、+、~ - 伪类如
:hover允许,但会使权重升为0-1-1,仍远低于嵌套选择器,推荐改用.button--hovered - 一旦出现
.card .card__title或button.search-form__submit,权重立刻跳到0-2-0或更高,BEM 的权重控制即失效
BEM 权重稳定的三个硬性前提
0-1-0 不是自动生效的魔法,它依赖三件事同时成立:
- CSS 文件引入顺序可控:
.button--disabled必须在.button之后加载,否则层叠顺序翻车 - HTML 中 modifier 类不能单独存在:
class="button--disabled"无效,必须是class="button button--disabled" - 构建工具不能截断或转义下划线:比如
css-loader的localIdentName若配置为[hash:base64]却没保留__,.menu__item可能变成.menuitem_abc123,直接失效
常见破防写法与后果
很多项目以为用了双下划线就是 BEM,实际权重早失控:
-
.sidebar .widget h3→ 权重0-1-1(1 class + 1 element),想覆盖就得写更重的选择器,恶性循环 -
.button--primary:hover合法,但若和第三方库的.btn-primary:focus(0-2-0)对撞,谁排后面谁赢,不可控 -
[class*="button"]权重虽是0-1-0,但语义模糊,DevTools 里根本看不出它对应哪个组件
Modifier 叠加时样式覆盖错乱的根本原因
不是 BEM 不支持多个 modifier 共存,而是你让不同维度的样式修改了同一属性:
-
.button--primary设background,.button--large也设background→ 后声明的必赢,哪怕语义上完全正交 - 正确做法:每个 modifier 只管自己那块地 ——
.button--primary管颜色,.button--large管padding和font-size,.button--disabled管opacity和cursor - 检查所有 modifier 是否重复定义相同 CSS 属性(尤其是
background、border、color)
最常被忽略的一点:BEM 的权重稳定性,完全建立在开发者不手动干预层叠顺序的基础上。一旦有人为了“快速修复”在某处加了 !important,整个链路的信任就崩了——后续所有 modifier 都得跟着加,最后谁都压不住谁。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











