双下划线__是BEM中块与元素的唯一合法连接符,表示直属组成部分关系;单下划线_无语义且违反规范,会导致工具链解析失效、协作混乱和维护困难。

双下划线 __ 是块与元素的唯一合法连接符
它不是“分隔符”,而是语义标记:表示“这个类名描述的是该块的直属组成部分”。比如 user-card__avatar 意味着头像属于用户卡片这个块,且是第一层结构成员。一旦写成 user-card_avatar(单下划线)或 user-card__avatar__icon(三层),BEM 工具链、团队协作和样式可维护性都会出问题。
-
__只能出现在块名之后,且仅允许一层;不能用于元素内部再分层 - 浏览器不解析
__,但它被 PostCSS 插件、Sass 函数、文档生成器等依赖来识别结构 - 写错成单下划线时,
menu_item会被当成一个普通单词,失去“menu 块下的 item 元素”这层语义
单下划线 _ 在 BEM 中没有标准语义,应避免使用
BEM 规范里 _ 不代表任何结构关系。有些老项目或误读资料会用 block_element 表示元素,但这违反 BEM 原则——它模糊了块/元素边界,也容易和变量名、文件名中的下划线混淆。官方资料明确指出:_ 不是 BEM 的语法组成部分。
- 所有元素必须用
__,修饰符必须用--,中间绝不能混用_ - 多词元素名用短横线
-连接,如search-form__submit-button,不是search-form__submit_button - 如果看到
button_disabled,它大概率是手写错误或非 BEM 项目迁移残留,不是合规写法
为什么不能用单下划线替代双下划线?
因为 BEM 工具链靠精确符号识别层级。把 header__nav 写成 header_nav 后,Sass 中的 @function bem-element 无法提取出 nav 是 header 的元素;自动化 CSS 提取工具会跳过该类名;设计系统文档也可能漏掉这个“元素”。这不是风格偏好,而是解析失效的实际后果。
- 构建时:PostCSS 插件如
postcss-bem-linter会报Invalid BEM element syntax - 运行时:无直接影响,但团队新成员会困惑
form_input和form__input是否等价 - 重构时:若某天想提取
nav成独立块,header_nav类名无法安全重命名,而header__nav明确表明它本就该被替换为nav块
修饰符用双短横线 --,和下划线完全无关
修饰符是状态或变体,格式只能是 block--modifier 或 block__element--modifier。有人误以为 button_primary 是合法修饰符,其实它既不是 BEM 修饰符(缺 --),也不是元素(缺 __),更不是块(含下划线)。这种写法会让修饰符逻辑失控——比如同时存在 button_primary 和 button--primary,CSS 优先级和维护成本立刻翻倍。
立即学习“前端免费学习笔记(深入)”;
-
--和__是强绑定的:有__才可能有__element--modifier - 修饰符名必须聚焦语义,如
--disabled、--loading,不能是--blue这类视觉描述 - 伪类状态(
:hover、:focus)不用修饰符,它们由 CSS 自身控制
__ 当成“看起来顺眼的分隔符”来用。它其实是 BEM 解析器的锚点——少一个下划线,整个类名在工具链里就“失联”了。


















