aria-disabled="true" 仅声明禁用语义,不自动置灰或移出焦点流;需手动添加CSS(如opacity和cursor)、JS拦截事件、同步更新tabindex与DOM状态。

aria-disabled 本身不会置灰,必须手动加 CSS
很多人以为写了 aria-disabled="true" 按钮就会自动变灰,其实它完全不触发任何样式变化。浏览器只把它当一个语义标记,连 opacity 都不会动一下。想让视觉上“看起来禁用”,得自己写 CSS 规则,比如:
.btn[aria-disabled="true"] {
opacity: 0.5;
cursor: not-allowed;
}
注意:别只靠 opacity,还得配 cursor: not-allowed,否则鼠标悬停时游标还是手型,用户会误判可点击性。
留焦点 ≠ 允许聚焦,得用 tabindex="-1"
“留焦点”这个说法容易误导——aria-disabled="true" 不影响聚焦行为,但默认情况下,像 div 或 span 这类元素本来就不能被 Tab 聚焦。如果你希望它“能被键盘到达但不可操作”,就得显式设 tabindex="-1"。这不是为了“留”,而是为了“可控地进”:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
-
tabindex="-1"表示该元素不能通过 Tab 键顺序进入,但可通过 JSfocus()主动获得焦点 - 若你真需要它出现在 Tab 流中(比如作为步骤导航按钮),应设
tabindex="0"+aria-disabled="true"+ 完整事件拦截 - 漏掉
tabindex="-1",键盘用户可能 tab 进去后按回车/空格,照样触发 click
为什么不能只靠 disabled 属性实现“留焦点”
原生 disabled 属性会让元素彻底退出焦点流(tabindex 失效、focus() 无效、Tab 键跳过),所以它做不到“视觉禁用但焦点可停留”。这正是 aria-disabled="true" 的存在意义:仅声明状态,不接管行为。但代价是你必须补全三件事:
立即学习“前端免费学习笔记(深入)”;
- CSS 控制视觉:
[aria-disabled="true"] { pointer-events: none; opacity: 0.5; } - JS 拦截交互:
if (el.getAttribute('aria-disabled') === 'true') return;放在click和keydown(Enter/Space)里 - DOM 状态同步:业务逻辑变更时,必须同时更新
aria-disabled、tabindex和 class 名,缺一不可
常见翻车点:灰了但还能点,或焦点卡死
最常被忽略的不是怎么写属性,而是状态更新时机。比如表单校验通过后,JS 忘记移除 aria-disabled="true",或者没把 tabindex 从 "-1" 改回 "0",结果屏幕阅读器说“已禁用”,用户却不知道为什么不能操作,也无法用键盘继续往下走。更隐蔽的是:如果用了 pointer-events: none,但没同步处理 focus() 后的键盘响应,焦点就“悬在空中”——看不见、点不了、Tab 也出不去。


















