必须用 aria-disabled="true" 仅当无法使用原生 disabled 属性时(如 div 模拟按钮),原生表单元素一律用 disabled;aria-disabled="false" 违反规范,应避免;禁用自定义控件需同步设置 aria-disabled="true"、tabindex="-1"、pointer-events: none 及 js 事件拦截。

直接用 disabled 属性,别碰 aria-disabled——除非你正在写自定义控件,且明确知道它只是“告诉屏幕阅读器‘这东西现在不能点’”,不拦点击、不拦聚焦、不拦回车。
什么时候必须用 aria-disabled="true"
只在无法使用原生 disabled 的场景下才考虑它:比如用 div 或 span 模拟按钮、用 a 标签做操作入口、或框架组件内部封装了原生按钮但暴露不了 disabled 属性。
-
button、input、select等原生表单元素,一律用disabled,加aria-disabled不仅多余,还可能让读屏器困惑 - 写了
aria-disabled="true"却没同步设tabindex="-1",键盘用户 tab 过去照样能按回车触发事件 - 只靠 CSS 灰化 +
aria-disabled="true",鼠标悬停仍可点击——pointer-events: none必须配,或 JS 中手动event.preventDefault()
aria-disabled="false" 是个危险信号
WAI-ARIA 规范里,aria-disabled 只接受 "true" 字符串值;显式写 aria-disabled="false" 不是“启用”,而是向辅助技术发出错误状态提示,部分读屏器会误读为“禁用失败”或跳过该元素。
- React 中推荐写法:
aria-disabled={isDisabled ? "true" : undefined},别用{String(isDisabled)} - Vue 中用
:attr="{ 'aria-disabled': isDisabled ? 'true' : null }",避免渲染出false字符串 - 服务端渲染或 SSR 框架中,若初始 HTML 里出现
aria-disabled="false",会被解析为真实属性,后续 JS 也难清理干净
真正禁用一个自定义按钮要动几处
缺一不可。少一步,就等于对键盘用户和屏幕阅读器撒谎。
- HTML 加
aria-disabled="true"和tabindex="-1" - CSS 加
[aria-disabled="true"] { pointer-events: none; opacity: 0.5; cursor: not-allowed; } - JS 绑定
click和keydown(监听 Enter/Space),开头加判断:if (el.getAttribute('aria-disabled') === 'true') return - 视觉反馈必须和语义一致:灰度、禁用游标、无 hover 动效,三者同步更新
最常被忽略的不是代码怎么写,而是“禁用状态是否随业务逻辑实时同步”。比如步骤未完成时按钮禁用,但用户填完字段后 JS 没及时清除 aria-disabled 或恢复 tabindex,焦点就会卡死在不可交互的节点上——这时候屏幕阅读器说“已禁用”,用户却不知道为什么不能继续。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











