role="complementary" 是老旧读屏器识别 aside 的刚需,需配合唯一 aria-label、正确嵌套、aria-live 和键盘可达性保障可访问性。

role="complementary" 是老旧读屏器识别 aside 的刚需
现代浏览器基本能正确解析 aside 的语义,但 IE11、JAWS 2018 以下或部分 NVDA 旧版本会完全忽略它,当成普通 div 处理。显式加上 role="complementary" 能强制激活地标(landmark)识别,让用户用快捷键 D 直接跳转到该区域。
这不是可选项,而是兼容性兜底手段。不加的话,测试时可能发现:屏幕阅读器播报“段落”“按钮”,但从不提“侧边栏”或“补充内容”——用户根本不知道那里有可操作元素。
注意:role="sidebar" 不是 WAI-ARIA 标准角色,会被直接忽略,别写。
多个 aside 共存时,每个都必须有唯一 aria-label
如果页面同时存在“作者简介”和“延伸阅读”两个 aside,只写 role="complementary" 是不够的。读屏器会连续报出两个“complementary”,用户无法区分哪块是啥。
必须为每个 aside 配独立的 aria-label:
<aside role="complementary" aria-label="作者简介">...</aside><aside role="complementary" aria-label="延伸阅读">...</aside>
常见错误:用 aria-labelledby 指向内部 h2,但该标题被 CSS 隐藏或未渲染,导致标签为空;或多个 aside 共用同一个 ID,引发 ARIA 属性冲突。
aside 嵌套位置错误会让 role 失效
role="complementary" 的语义有效性依赖于父级容器逻辑。把 aside 错放在 header 或 footer 里,等于告诉辅助技术:“这是页眉的附属内容”——但实际可能是全站广告位,语义断裂直接导致上下文误判。
正确嵌套方式取决于服务范围:
- 服务单篇文章 → 放在
article内部 - 服务整页主内容 → 与
main并列,同级置于body - 服务某个章节 → 放在对应
section内
反例:,这种结构下即使加了 role 和 aria-label,读屏器也会优先按 header 上下文解释,失去“补充全页内容”的本意。
动态插入的 aside 必须配 aria-live
JS 加载的“相关文章”列表或广告位,如果只是插入 DOM 而不触发可访问性更新,读屏器不会主动播报新内容。用户可能卡在旧状态,完全不知侧边栏已刷新。
解决方案是给 aside 容器加 aria-live="polite",并确保它在插入时已存在于 DOM 中(不能等 JS 插入后再补属性):
<aside role="complementary" aria-label="相关推荐" aria-live="polite"></aside>
注意:aria-live 对 display: none 或 visibility: hidden 的元素无效;折叠状态下若保留该区域,需配合 aria-hidden="true" + inert 属性禁用交互,且要用 JS 在 resize 事件中同步更新这些属性。
最常被忽略的一点:role 和 aria-label 只解决“怎么叫”,不解决“怎么进”。aside 默认 tabindex="-1",内部 input 或 button 才决定键盘是否可达——如果忘了检查子元素的 tabindex 或被 CSS 覆盖,整个侧边栏对键盘用户就是不可达的黑盒。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











