BEM中__是块与元素的唯一分隔符,_非官方符号且禁用;混用会导致工具链失效、语义模糊、IDE跳转失败及重构风险。

初学者写错 BEM,90% 是因为混淆了 _ 和 __ 的语义——它们不是“多打一个下划线就更规范”,而是代表完全不同的抽象层级。
为什么_和__不能混用
BEM 解析器、Sass 嵌套规则、IDE 类名跳转、CSS 工具链(如 PostCSS 插件)都依赖 __ 作为块与元素的**唯一分隔符**。一旦用 _ 替代,工具就无法识别 header_logo 是块名的一部分,还是块 header 下的元素 logo。
-
header__logo→ 明确:块header的直属元素logo -
header_logo→ 模糊:可能是块名含下划线,也可能是拼写错误;Sass 的&__logo不会匹配它 -
button--large__icon→ 错误:修饰符--large后不能接__;应为button--large(整体变体),或button__icon--large(仅图标变体,需有明确设计定义)
__ 只能出现在块名之后、且仅一层
双下划线不是“嵌套深度指示器”,它只标记“这个元素直接属于这个块”。哪怕 DOM 结构是 <menu><item><icon></icon></item></menu>,icon 仍应写作 menu__icon,而不是 menu__item__icon。
- 正确:
menu__item、menu__icon、menu__divider(全部平级归属menu) - 错误:
menu__item__text、user-card__content__avatar——这会让团队误以为存在“内容块”,实际它只是user-card的一部分 - 深层结构难命名?优先考虑拆新块:
user-avatar比user-card__content__avatar更合理、可复用
_ 在 BEM 中基本不该出现
单下划线 _ 不是 BEM 官方符号,多数主流规范(包括 Sass/Less 工具链、BEM 官网、@bem/react)明确禁用它。你看到的 list_item 或 btn_primary,要么是旧项目遗留,要么是误读了“连字符”规则。
立即学习“前端免费学习笔记(深入)”;
- 多单词块名用短横线:
user-card、form-field(-仅作连接符,无语义) - 修饰符必须用
--:button--disabled、input--error,不是button_disabled - 如果真需要表达状态组合(极少见),应合并语义:
button--loading-primary,而非button_loading_primary - 所有预处理器的
&__item、&--hover语法,都只认__和--,_会被忽略或报错
最常被忽略的一点:BEM 的长类名不是为了“好看”,而是为了静态可分析性。你手写 className={`${base}_${element}`} 看似省事,但 IDE 找不到定义、搜索 logo 会漏掉 header__logo、重构改名时根本不敢批量替换——这些不是“以后再优化”的问题,是写第一行 BEM 类名时就该卡死的边界。


















