原生 button 元素默认支持无障碍聚焦与交互,无需添加 tabindex="0" 或 role="button";禁用时应避免 disabled,改用 aria-disabled="true" 保持聚焦能力;仅当无可见文本时需通过 aria-label 或可见文本来提供可访问名称。

button 元素本身已支持无障碍聚焦,无需额外 standard attribute
原生 button 默认可被键盘 Tab 导航、Enter/Space 触发,且被屏幕阅读器识别为“按钮”角色——这是 HTML 语义自带的无障碍能力。你不需要加 tabindex="0" 或 role="button",反而可能破坏默认行为。
哪些 standard attribute 会意外破坏聚焦能力
常见错误是误用 standard attribute,导致按钮失去可聚焦性或语义断裂:
-
disabled:设为true后按钮不可聚焦、不可触发,但若只是视觉禁用(如灰化),应改用aria-disabled="true"+ CSS 控制样式,保留聚焦能力供屏幕阅读器感知状态 -
hidden:整个元素从可访问树中移除,屏幕阅读器和键盘都无法到达;若需条件隐藏,优先用display: none或visibility: hidden,它们与hidden的语义影响不同 -
tabindex="-1":虽允许脚本调用.focus(),但排除在 Tab 顺序外——除非你明确要“只脚本聚焦、不键盘导航”,否则不要加
真正需要加的 standard attribute 只有这一个
当按钮文本为空(比如仅用图标 ✕ 或 SVG),必须提供可读文本,否则屏幕阅读器无法说明功能:
- 优先用
textContent或可见子文本,例如:<button>关闭对话框</button> - 若必须视觉隐藏文字,用
aria-label(注意:它是 ARIA 属性,不是 standard attribute);standard attribute 中唯一能间接补足的是title,但它仅在悬停时生效、不被所有屏幕阅读器可靠读出,**不推荐作为无障碍主方案**
结论:别为了“确保聚焦”而乱加 attribute。聚焦能力来自元素类型和 DOM 状态,不是靠属性堆砌。
focus() 失败的典型原因和修复点
即使用了正确 button,脚本调用 .focus() 仍可能失败:
- 元素未挂载到 DOM:先
appendChild()再.focus() - 父容器有
inert或aria-hidden="true":这些会阻断整个子树的可访问性 - 样式导致不可见但未移除:检查
opacity: 0或position: absolute; left: -9999px是否让元素脱离渲染流——offsetParent === null时.focus()无效 - 浏览器尚未完成样式计算:用
requestAnimationFrame(() => btn.focus())替代setTimeout(() => btn.focus(), 0)
最常被忽略的是:按钮是否真的在当前可访问上下文中——比如它被包裹在 aria-hidden="true" 的模态背景层里,或者父级 dialog 尚未调用 showModal(),此时 focus 操作会被静默忽略。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











