bem规范要求按钮根类名必须是独立block(如btn),变体用双短横线修饰符(btn--primary);element(btn__icon)须为直接子节点;修饰符需完整覆盖交互状态。

按钮的根类名必须是独立 Block,不能叫 btn-primary 或 submit-btn
Block 名要代表「组件本身」,不是它的状态或用途。写成 btn-primary 会让别人误以为这是个新组件,而不是 btn 的一种变体;submit-btn 则把业务语义(提交)和结构混在一起,换个场景(比如“取消”按钮)就得重写类名。
正确做法是只用一个基础类名:btn。所有变体都基于它叠加修饰符,比如 btn--primary、btn--cancel、btn--loading。这些修饰符之间互不耦合,可以自由组合:btn btn--primary btn--large btn--disabled 是合法且预期的行为。
- 禁止用单短横线(
btn-primary)、下划线(btn_primary)或驼峰(btnPrimary)代替双短横线 -
btn必须出现在每个按钮元素上,修饰符不能单独使用——btn--disabled单独写在 HTML 里无效 - Block 名别用泛标签名,比如
button或link;也别加前缀如my-btn,除非你真有命名空间冲突
btn__icon 和 btn__text 是合法 Element,但不能嵌套三层
Element 表示按钮内部的、逻辑上属于它的子部分。图标和文字是最典型的两个:btn__icon、btn__text。它们必须是 btn 元素的**直接子节点**,中间不能隔一层没命名的 div。
常见错误是写成 btn__content__title 或 btn__icon__spinner——BEM 不允许 Element 再有子 Element。如果按钮里需要加载图标,应该用 btn__icon--loading,而不是造一个新层级。
-
btn__icon合法,btn-icon或btn_icon都非法:前者被当成独立 Block,后者分隔符错 - Element 名不重复 Block 名,
btn__btn-icon是冗余写法 - 如果 DOM 结构是
<button class="btn"><span class="btn__text">OK</span></button>,那没问题;但如果写成<button class="btn"><div><span class="btn__text">OK</span></div></button>,btn__text就失效了——它已不是btn的直接子元素
修饰符位置不能乱:图标方向用 btn--icon-left,不用 btn__icon--left
图标在左还是在右,是按钮整体的布局特征,不是图标的内在属性。所以修饰符必须作用于 Block(btn),而不是 Element(btn__icon)。
写成 btn__icon--left 是典型越界:它暗示“这个图标自己决定位置”,但实际布局由父容器控制。CSS 里应该用 flex-direction 或 order 去调整 btn__icon 和 btn__text 的顺序,而不是给图标加定位类。
- 正确:
<button class="btn btn--icon-left"><span class="btn__icon"></span><span class="btn__text">提交</span></button> - 错误:
<button class="btn"><span class="btn__icon--left"></span></button> -
btn__icon--loading合法,因为加载态是图标自身的视觉变体;但btn__icon--left违反职责分离
禁用态、加载态这些状态类,必须显式覆盖交互属性
BEM 类名只是语义标记,真正起作用的是 CSS 规则。很多团队写了 btn--disabled 却只改背景色和文字灰度,结果按钮还能点、光标还是手型、键盘仍可聚焦——这不是 BEM 写错了,是样式没写到位。
关键点在于:所有修饰符规则必须用单类选择器定义,且权重一致。别写 .btn.btn--disabled,直接写 .btn--disabled;同时确保它能覆盖 :hover、:focus 等伪类。
-
.btn--disabled至少应包含:pointer-events: none、cursor: not-allowed、opacity: 0.6(别只靠颜色) - 避免在修饰符里用
!important,否则叠加时会失控;也不要用后代选择器如.btn--disabled .btn__text,这破坏 BEM 的低权重原则 - 布尔型状态建议用
is-前缀,比如is-loading,和btn--loading并存也可,但别混用:btn--is-loading是错的
btn__icon 是否真在 DOM 里作为 btn 的直接子节点,btn--disabled 是否真的让按钮不可交互。写对名字只是第一步,后续样式、结构、JS 控制必须同步对齐。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











