aria 属性不是无障碍开关,而是原生语义不足时对辅助技术的必要补充;必须在原生标签无法准确传达行为或状态时使用,且需与 javascript 全量同步行为与状态,否则比不加更误导用户。

aria-* 属性不是“让网页变无障碍”的开关,而是当 HTML 原生语义表达不了动态状态或关系时,给辅助技术补一句“人话”——它只在必要处起效,加错地方反而破坏体验。
aria-\* 什么时候必须加?
只有原生标签无法准确传达行为或状态时才用。比如:
<div> 模拟下拉菜单 → 必须加 <code>role="listbox"+aria-expanded+aria-activedescendant- 纯
<svg></svg>图标按钮 → 必须加aria-label或aria-labelledby,否则读屏器跳过不读 - 无限滚动容器插入新条目 → 必须加
aria-live="polite",否则用户听不到新增内容 - 模态框用
<div class="modal"> 实现 → 必须同时设 <code>role="dialog"、aria-modal="true"、aria-labelledby别给
<button></button>加aria-disabled="true"还手动控制样式——它原生就支持disabled属性,重复设置易导致状态不同步。常见误用:aria-hidden="true" 的三大陷阱
aria-hidden="true"不是“隐藏元素”,只是告诉读屏器“别管这个节点及其所有子节点”。它和视觉表现完全解耦:- 对整个导航栏父容器加
aria-hidden="true",再用 JS 切换显示/隐藏 → 子项按钮永远无法被聚焦,键盘用户卡死 - 在模态框打开时给
加aria-hidden="true"→ 背景内容被跳过,但焦点没锁住,Tab 键仍能切到不可见区域 - 父元素设了
aria-hidden="true",子元素再写aria-hidden="false"→ 完全无效,继承强制隐藏
真正需要“视觉隐藏但读屏可读”时,用
.sr-only类(靠position: absolute; clip: rect()移出视口),而不是aria-hidden。
html-to-pptx-converter下载使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
role 和 aria-\* 必须协同生效
单独写
role="switch"没用,必须配齐三要素:-
aria-checked="true"或"false"表示当前状态 -
tabindex="0"让它可获焦 - 监听
Space键并更新aria-checked值,同时触发视觉反馈
同理,
role="tablist"要搭配每个role="tab"的aria-selected和aria-controls,否则读屏器只知“这是个 tab 列表”,不知哪个激活、连向哪块面板。验证是否真有效?别信 DevTools 的 Accessibility 面板
它只检查属性是否存在,不校验逻辑是否闭环。真实验证必须:
- 用 NVDA(Windows)或 VoiceOver(macOS)完整走一遍交互流程:打开/关闭、Tab 导航、状态切换
- 检查
aria-live区域是否真被朗读——注意 DOM 更新方式:innerHTML替换会丢失绑定,推荐用textContent或appendChild - 确认读屏器当前模式(浏览/虚拟光标)是否影响
aria-live="polite"的触发时机
最常被忽略的点:ARIA 不是贴纸,它是契约——你声明了
role和aria-*,就得用 JS 全量实现对应行为与状态同步,否则比不加更误导用户。 - 对整个导航栏父容器加










