aria只是辅助技术的“传话工具”,不能替代语义html或自动提供交互行为;必须优先使用原生标签,手动补全键盘支持、焦点管理与状态同步,确保语义、行为、样式一致。

ARIA 本身不提升可访问性,它只是给辅助技术“递话”的工具;用错或滥用反而会破坏可访问性。
ARIA 不是语义 HTML 的替代品
很多开发者以为加了 role="button" 就能让一个 <div> 变成真正的按钮——其实不行。它只告诉屏幕阅读器“这看起来像按钮”,但不会自动绑定空格/回车触发、键盘焦点管理、:focus-visible 样式或鼠标事件。用户仍得自己补全交互逻辑。
<p>真正该做的是:优先用原生语义标签。比如用 <code><button></button> 代替 <div role="button">,用 <code><nav></nav> 代替 <div role="navigation">。
<ul>
<li>原生元素自带键盘导航、焦点行为和隐含 ARIA 语义</li>
<li>ARIA 无法修复缺失的键盘支持(如按 Tab 进不去、按 Enter 没反应)</li>
<li>某些 <code>role(如 application)甚至会让屏幕阅读器退出标准浏览模式,增加用户认知负担
aria-hidden 和 display: none 的区别很关键
aria-hidden="true" 只隐藏给辅助技术的内容,视觉上仍可见;而 display: none 或 visibility: hidden 会同时移出渲染树和可访问树——两者效果不同,不能混用。
常见错误:给 loading 遮罩层加 aria-hidden="true" 却没禁用底层内容的焦点,导致键盘用户能 tab 到被遮住的按钮上。
- 遮罩层应设
aria-modal="true"+inert(现代浏览器)或手动tabindex="-1"移除焦点流 - 动态显示/隐藏内容时,优先用
hidden属性而非aria-hidden,更可靠 -
aria-hidden="true"不影响子元素——除非子元素显式设aria-hidden="false"
动态内容更新必须配 aria-live
单页应用里用 JS 更新状态(如表单校验提示、通知弹窗),若不声明 aria-live,屏幕阅读器大概率不会朗读变化。
但不是所有场景都适合 aria-live="polite" 或 "assertive":
-
polite:等当前语音说完再读,适合非紧急信息(如“用户名可用”) -
assertive:立即中断当前朗读,仅用于错误或关键操作反馈(如“支付失败”) - 避免对高频更新区域(如计时器)设
aria-live,会导致朗读轰炸 - 不要把
aria-live加在会频繁重渲染的容器上(如整个<main></main>),应精准包裹变动节点
最常被忽略的一点:ARIA 属性本身没有 DOM 行为约束,aria-expanded="true" 不会让下拉菜单真的展开,aria-selected="true" 也不会让选项高亮——这些全是开发者要手动同步的。可访问性不是加几个属性就完事,而是语义、行为、样式三者必须一致。











