ARIA属性需在HTML语义缺失时精准补位,优先使用原生语义元素;仅当组件行为或状态无法用HTML表达时才引入ARIA,且须配合JS/CSS实现对应功能。

ARIA 属性不是“加了就无障碍”,而是“在语义缺失时精准补位”——HTML 原生语义元素(如 <button>、<nav>、<main>)永远优先于 role 和 aria- 属性。盲目堆砌 aria-hidden="true" 或乱设 role="button" 反而会破坏读屏体验。
哪些情况必须用 ARIA?
只有当 HTML 语义无法表达组件行为或状态时,才引入 ARIA:
- 自定义下拉菜单(
<div class="dropdown">)需要role="listbox"+aria-expanded+aria-activedescendant - 动态加载内容区域(如无限滚动列表)需用
aria-live="polite"告知读屏器新条目已插入 - 图标按钮(仅含
<svg>)必须配aria-label或aria-labelledby,否则读屏器会跳过或读作“图形” - 模态框(
<div class="modal">)要同时设role="dialog"、aria-modal="true"和aria-labelledby指向标题
role 和原生标签冲突怎么办?
浏览器和读屏器对原生标签的语义有强共识,强行覆盖会出问题:
- 不要给
<button>加role="link"——它就是按钮,想让它像链接行为,该用 JS 控制逻辑,而不是欺骗辅助技术 -
<input type="checkbox">已自带role="checkbox"和aria-checked,再手动加aria-checked="true"可能导致状态不同步 - 若用
<span>模拟开关,必须完整实现:role="switch"+aria-checked+tabindex="0"+ 键盘事件(Space)+ 视觉反馈
aria-hidden 的坑比你想象的多
aria-hidden="true" 不是“隐藏给所有人看”,它只告诉辅助技术“忽略这个节点及其所有子节点”——但视觉用户仍能看到,JS 仍可操作它:
立即学习“前端免费学习笔记(深入)”;
- 别对整个导航栏加
aria-hidden="true"后又靠 CSSdisplay: none隐藏——读屏器已跳过,CSS 隐藏只是锦上添花;但如果只加 CSS 隐藏没加aria-hidden,读屏器仍会朗读不可见内容 -
aria-hidden="true"父元素下的子元素,即使设aria-hidden="false"也无效(继承强制隐藏) - 模态框打开时,常有人把
<body>设为aria-hidden="true",结果背景内容被读屏器跳过——正确做法是用inert属性(现代浏览器支持)或用tabindex="-1"+focus()锁定焦点在模态框内
验证 ARIA 是否生效?别只信浏览器检查器
DevTools 的“Accessibility”面板只显示属性是否存在,不校验逻辑是否正确:
- 用 NVDA(Windows)或 VoiceOver(macOS)真实测试交互流程:打开/关闭、Tab 导航、读取状态变化
- 检查
aria-live区域是否真被朗读——它依赖插入位置、DOM 更新方式(innerHTML替换可能丢失)、以及读屏器当前模式(浏览/虚拟光标) - 运行
axe-core(Chrome 插件或 CLI)扫描,重点看aria-allowed-attr、aria-required-children这类规则,它们能发现role="tree"下漏了role="treeitem"这类硬性错误
最常被忽略的一点:ARIA 属性本身不触发任何行为,aria-expanded="true" 不会让下拉展开,aria-disabled="true" 也不会禁用点击——这些必须由 JS 和 CSS 协同实现,否则就是“说一套做一套”,辅助技术用户反而更困惑。



















