必须用btn--disabled而非btn-disabled或btn_disabled,因--是bem修饰符唯一合法分隔符,确保工具链识别状态语义、避免误删;且需同步设置disabled属性、aria-disabled和pointer-events等,实现视觉、交互与语义三者一致。

必须用btn--disabled,不是btn-disabled或btn_disabled
BEM 规范里--是修饰符的唯一合法分隔符,它让工具链(PurgeCSS、stylelint-selector-bem-pattern、IDE 补全)能准确识别这是「按钮的禁用状态」,而不是一个新块或拼写错误的类名。写成btn-disabled会被当成独立组件,SSR 构建时可能被 PurgeCSS 当作未使用类删掉;btn_disabled里的下划线无语义约定,CI 流程里容易漏检。
btn--disabled必须配合disabled属性使用,不能只靠 CSS 类
仅加btn--disabled类,键盘用户仍可聚焦、屏幕阅读器无法感知、表单提交逻辑可能跳过校验——BEM 修饰符只管视觉,DOM 属性才管语义与行为。
- 正确做法:
el.classList.toggle('btn--disabled', isDisabled); el.disabled = isDisabled; - React/Vue 中注意:props 变化后要真实触发 class 更新,不能只改 state 却没映射到 class 列表
- 禁止手动拼字符串:
el.className += ' btn--disabled'—— 易重复、难移除、漏空格
禁用样式不能只靠opacity或filter,需显式重置交互属性
只设opacity: 0.6会让按钮看起来灰了,但鼠标悬停时仍可能触发:hover高亮,光标还是pointer,甚至还能被键盘聚焦。禁用态必须同步视觉、交互、语义三者。
- 必须显式设置:
cursor: not-allowed、pointer-events: none(推荐)、tabindex="-1"(若非原生 button) - 避免仅依赖
:disabled伪类:React 不一定把disabled={true}同步为 HTML 属性,SSR 场景下会失效 - 非原生元素(如
div或自定义组件)不支持:disabled,必须用class+aria-disabled="true"+tabindex="-1"
多个状态共存时,别写btn--disabled--loading,要并列+显式叠加
btn--disabled--loading违反 BEM 语法,它不是修饰符,而是新块名,JS 控制困难,工具链无法提取,且语义模糊——到底是“禁用的加载态”,还是“一种叫 disabled-loading 的特殊按钮”?
- 正确写法:
btn btn--disabled btn--loading,两个修饰符平级并存 - CSS 分开定义:
.btn--disabled { opacity: 0.6; }、.btn--loading { cursor: wait; } - 需要叠加效果(如禁用时 loading 图标也要变灰)时,单独写:
.btn--disabled.btn--loading { opacity: 0.4; },但仅限必要场景 - 构建工具(如 PurgeCSS)可能删掉动态添加的类,需在
safelist中保留正则:/btn--(disabled|loading|error)/
btn--disabled btn--loading就一定让禁用样式优先——得看 CSS 文件里哪条规则写在后面。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











