aria-disabled="true"仅提供语义提示,不阻止交互;disabled才真正禁用元素并影响表单提交。非表单元素必须用aria-disabled配合tabindex、CSS和JS手动控制,且需正确绑定避免语义冲突。

aria-disabled="true" 不拦点击,disabled 才真禁用
写了 aria-disabled="true",按钮照样能点、能聚焦、能回车触发——它只告诉屏幕阅读器“这东西现在不能用”,不改变任何 DOM 行为。而 disabled 是浏览器原生硬控制:自动屏蔽焦点、阻止所有交互、表单提交时直接剔除该字段值。
哪些元素必须用 aria-disabled 而不是 disabled
只有 button、input、select、textarea 这类原生表单控件才识别 disabled 属性;div、span、a、li 等非表单元素写了 disabled 也毫无效果。
- 用
div role="button"模拟按钮?必须用aria-disabled="true"作为起点 - 但光写这个不够:还得加
tabindex="-1"防键盘聚焦 - 加 CSS:
[aria-disabled="true"] { pointer-events: none; opacity: 0.5; } - JS 中监听
click和keydown,检查el.getAttribute('aria-disabled') === 'true'后调用event.preventDefault()
React/Vue 里动态绑定 aria-disabled 的坑
框架里直接写 aria-disabled={isDisabled},布尔 false 会渲染成 aria-disabled="false" —— 这违反 WAI-ARIA 规范,部分读屏器可能误读为“禁用失败”或跳过该元素。
- React 正确写法:
aria-disabled={isDisabled ? "true" : undefined} - Vue 正确写法:
:attr="{ 'aria-disabled': isDisabled ? 'true' : null }" - 别混用:
disabled和aria-disabled="true"同时存在,会造成语义冲突,某些读屏器报“状态矛盾”警告 - 更隐蔽的坑:
aria-disabled="false"不等于“启用”,它只是个无效标记;没这个属性才等价于 false
readonly 和 disabled 提交行为完全不同
如果后端收不到某个字段,大概率是前端误用了 disabled 而不是 readonly。表单序列化(new FormData(form)、form.submit())会彻底过滤掉所有 disabled 元素的值;而 readonly 元素的值照常提交。
立即学习“前端免费学习笔记(深入)”;
-
readonly只对input[type="text"]、input[type="password"]、textarea生效;select、checkbox加了也白写 -
disabled支持fieldset批量禁用,语义清晰、兼容性好,比逐个加更可靠 - 需要用户能复制内容(比如 API Key 展示),必须用
readonly——disabled下连聚焦都不行
aria-disabled 从不自动影响样式或交互逻辑,它只是一个语义信号;而开发者常常只改了这个属性,就以为按钮“已经禁用了”。



















