按钮禁用状态必须用 btn--disabled,加载状态用 btn--loading,二者可共存但需显式定义组合样式;BEM 修饰符仅允许双连字符 --,禁止嵌套或业务语义命名,CSS 权重恒为 0,1,0,失效多因类名未添加、加载顺序错误或内联样式覆盖。

按钮禁用状态必须用 btn--disabled,不是 btn-disabled 或 btn_disabled
BEM 修饰符的唯一合法分隔符是双连字符 --,写成 btn-disabled 在 CSS 里就是一个普通类名,不是修饰符——构建工具可能误删,DevTools 里看不到它和 btn 的语义关联,协作时别人会当成新组件去改。
常见错误包括:btn-primary-disabled(耦合命名,JS 控制时要拼字符串,易漏空格);btn--primary--disabled(BEM 明确禁止嵌套修饰符)。
-
btn--disabled是唯一合规写法,它表达的是“按钮当前不可交互”这一明确 UI 状态 - 禁用态样式必须显式重置:
pointer-events: none、cursor: not-allowed、opacity(不能只靠颜色变灰) - JS 添加/移除必须用
element.classList.toggle('btn--disabled', isDisabled),避免手动拼接字符串
加载状态必须用 btn--loading,且样式应通过伪元素实现
加载态属于按钮的临时视觉变体,不是独立组件,所以不能新增子元素(比如 btn__loader),否则动画脱离按钮尺寸上下文,且无法响应 disabled 态的自动抑制行为。
正确做法是把所有加载逻辑收在 btn--loading 修饰符内,用 position: relative + ::after 插入 spinner,不影响按钮内容流布局。
立即学习“前端免费学习笔记(深入)”;
-
btn--loading必须绑定可验证的 UI 表现:有旋转图标、禁用点击、视觉反馈明确 - 禁止用业务词如
btn--pending或btn--network-error,它们不说明用户看到什么、能做什么 - 高频动态状态建议把
btn--loading规则写在 CSS 文件靠后位置,避免被静态状态覆盖
多个状态共存时,CSS 必须显式声明组合效果
BEM 允许 btn btn--primary btn--disabled btn--loading 同时存在,但 CSS 不会自动合并规则。如果 btn--loading 设了 cursor: wait,而 btn--disabled 写了 pointer-events: none,最终表现取决于层叠顺序,不是 class 顺序。
- 必须单独写组合选择器:
.btn--disabled.btn--loading { opacity: 0.6; } - 不要写
btn--disabled--loading—— 这不是 BEM 合法语法,也不利于 JS 动态控制 - 如果
btn--error和btn--loading同时出现,且需停掉 spinner 动画,就得显式重置:.btn--error.btn--loading .spinner { animation: none; }
修饰符类名权重恒为 0,1,0,失效通常不是因为“权重不够”
所有 BEM 单类选择器(如 .btn--disabled)的 specificity 都是 0,1,0。它没生效,99% 是三件事没对上:
- HTML 元素上根本没加上
btn--disabled—— JS 拼错了,比如写成className="btn disabled" - CSS 加载顺序反了:
btn.css在主题文件之后加载,导致默认规则盖掉了修饰符 - DevTools 里看到的 computed 值来自内联
style属性或 JS 注入样式,这类声明优先级高于任何外部 CSS
每次想加 !important 前,先打开 DevTools Styles 面板,点开被划掉的属性,看右边 specificity 数字——如果已经是 0,1,0 且排在目标规则之后,那问题一定不在 CSS 权重本身。


















