disabled属性是唯一可靠禁用方式,因它自动禁用样式、点击、键盘触发及表单提交;.disabled类仅视觉模拟,不阻止交互、焦点、事件冒泡与提交,且bootstrap 5已移除其语义支持。

直接加 disabled 属性是唯一能同时禁用样式、点击、键盘触发和表单提交的可靠方式;仅靠 CSS 类或 pointer-events: none 都会漏掉至少一种交互路径。
为什么 disabled 属性比 .disabled 类更可靠
Bootstrap 5 已移除对独立 .disabled 类的语义支持。你写 <button class="btn btn-primary disabled">提交</button>,按钮视觉可能变灰,但:
-
Enter或Space键仍可触发click事件 - 屏幕阅读器不会播报“已禁用”,除非你手动加
aria-disabled="true" - 表单提交时该按钮的值仍会被序列化(
disabled属性才阻止提交) - 父级事件委托(如
form.addEventListener('click', ...))仍可能捕获到它
正确做法永远是:<button class="btn btn-primary" disabled>提交</button>。框架会自动匹配 button:disabled 规则,应用 opacity: .65、pointer-events: none 和 cursor: not-allowed。
JS 动态控制禁用状态时的三个必要操作
用 JS 切换禁用状态不能只改 class,必须同步处理 DOM 属性、可访问性和业务逻辑:
- 设属性:
btn.disabled = true或btn.setAttribute('disabled', 'disabled') - 同步 ARIA:
btn.setAttribute('aria-disabled', 'true')(启用时用removeAttribute('aria-disabled')) - 检查状态再执行业务逻辑:
if (!btn.hasAttribute('disabled')) { /* 发请求 */ },别依赖 class 名判断
漏掉任一环节,都可能导致重复提交、键盘用户误操作或读屏软件误报。
pointer-events: none 的真实作用范围与副作用
这个 CSS 属性只屏蔽鼠标和触摸事件,对键盘焦点、Enter 触发、伪类(:hover、:active)完全无效:
- 加了
pointer-events: none后,按钮仍可被Tab聚焦,按Enter仍会触发click - 它的穿透特性会让点击落到父容器上,如果父级绑了事件委托,回调里
event.target可能还是这个按钮 - 子元素(比如图标
<i class="bi bi-x"></i>)即使设了pointer-events: auto,在多数浏览器中也无效
所以它只适合临时遮罩场景(如加载中 spinner),绝不能替代 disabled 属性做功能禁用。
链接型按钮(<a></a>)怎么安全禁用
<a></a> 不支持 disabled 属性,只能模拟。但模拟必须三件套齐备:
- 加
class="disabled"(触发 Bootstrap 的视觉样式) - 加
tabindex="-1"(阻止键盘聚焦) - 加
onclick="event.preventDefault(); return false;"或 JS 中统一拦截click并preventDefault()
缺任何一项,都会导致键盘用户能聚焦、能回车、能跳转——这在 WCAG 2.1 中属于严重可访问性缺陷。优先方案仍是把 <a></a> 改成 <button type="button"></button>。
最常被忽略的点:禁用状态不是“视觉变灰”就完事了,而是要确保它在所有输入通道(鼠标、触摸、键盘、辅助技术)下行为一致。一个没设 aria-disabled 的 disabled 按钮,在读屏软件里就是个“看不见的陷阱”。











