aria-selected必须配合role="tab"、role="option"等语义角色使用,设在tablist容器上无效;切换时需JS同步更新所有tab的aria-selected值并管理焦点,仅靠CSS类名无法被屏幕阅读器识别。

aria-selected 怎么设才被屏幕阅读器识别
直接写 aria-selected="true" 不一定生效,关键得配合角色(role)和语义结构。它只在特定可选容器中起作用,比如 role="tablist"、role="listbox"、role="grid" 这类有明确“选中态”含义的上下文中,屏幕阅读器才会播报“已选中”。单独给一个 div 加 aria-selected,基本没反应。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 先确认父容器是否设置了正确的
role(如tablist、listbox),且子项有对应角色(如tab、option) -
aria-selected应该由 JS 动态控制,不能靠 CSS 类名或静态 HTML 硬编码 - 避免同时使用
aria-selected="true"和aria-disabled="true"—— 逻辑冲突,部分读屏会忽略选中态
tab 切换时 aria-selected 同步失败的常见原因
很多开发者用 click 监听器切换 tab,但忘了手动更新 aria-selected 属性,或者更新了旧项却漏掉新项。更隐蔽的问题是:用了 preventDefault() 或事件冒泡中断,导致焦点没落到目标 tab 上,读屏无法感知当前焦点位置,进而无法关联 aria-selected 状态。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 切换时,先清除所有子项的
aria-selected="true",再给目标项设为true - 确保点击后调用
element.focus(),让键盘焦点同步到位 - 别依赖 CSS
:focus或.active类来判断状态 —— 读屏不看这些 - 用浏览器的“无障碍树”面板(Chrome DevTools → Elements → Accessibility 标签)实时验证属性是否更新
aria-selected 和原生 selected/checked 的区别
aria-selected 是纯语义标注,不影响表单提交、DOM 选择或默认行为;而 selected(<option>)和 checked(<input type="radio/checkbox">)是原生控件的状态,会参与表单数据收集。两者不能混用,也不自动同步。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 如果是自定义下拉菜单(非
select)、手风琴、标签页等,用aria-selected+ JS 控制逻辑 - 如果是真实表单控件,优先用原生
selected/checked,它们自带无障碍支持,无需额外加aria-selected - 切勿在
<option>上同时写selected和aria-selected—— 冗余且可能引发读屏重复播报
CSS 里怎么安全响应 aria-selected
可以用 [aria-selected="true"] 做样式钩子,但要注意:这个属性值是字符串,不是布尔,所以不能写成 [aria-selected](会匹配任意值,包括 "false")。另外,IE 不支持属性值带引号的选择器写法,但现代项目基本不用考虑。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 样式规则写成
[aria-selected="true"] { /* 样式 */ },明确匹配 - 别把交互逻辑(如 hover/focus)和
aria-selected样式耦合太紧 —— 比如用:hover覆盖选中态,对键盘用户不友好 - 如果需要兼容高对比度模式,记得给
[aria-selected="true"]加足够明显的视觉反馈(边框、背景色、图标变化等)
真正容易被忽略的是:aria-selected 的状态必须与焦点位置、键盘导航顺序、以及用户实际操作意图严格一致。哪怕 DOM 更新了,如果焦点没跟上,或者 JS 更新延迟了几毫秒,屏幕阅读器就可能读错。验证时别只看 HTML 源码,一定要用真实读屏工具(NVDA + Firefox 或 VoiceOver + Safari)走一遍键盘流。


















