属性 关系
aria-owns
当 DOM 结构无法表达父子关系时,在无障碍树中声明该关系,将被引用元素作为当前元素的子项重新归属,供辅助技术使用。这是一个强力工具,容易误用。
使用时机
仅当 DOM 无法将子元素放置在无障碍树所需位置时使用。最常见的场景是 combobox 的弹出 listbox:该列表因层叠上下文原因位于 <body> 末尾,但语义上属于 combobox。在 combobox 上使用 aria-owns 并指向 listbox 的 ID,可告知辅助技术将 listbox 视为其子项。
若能重构 DOM 使子元素成为真正的后代,应优先采用该方式。aria-owns 是应急手段——虽然有效,但它绕过了作者在标记与语义一致性方面最自然的检验机制。
行为说明
其值为以空格分隔的元素 ID 列表。无障碍树将按列出的顺序,把每个被引用元素重新归属为当前元素的子项,原 DOM 父级在无障碍树视图中将失去这些子项。
保持树结构有效的规则:
- 每个被引用的 ID 必须存在且唯一。
- 同一元素在同一时刻只能被一个父级通过
aria-owns归属。若两处同时归属同一元素,行为未定义。 - 不得将自身的祖先元素作为归属目标,否则会在无障碍树中形成循环。
- 被归属元素在 DOM 中仍须可达——允许
display: none,但完全游离于文档之外的元素不可归属。
常见错误
- 指向的 ID 不存在或在最新渲染中已被移除。
- DOM 本可直接嵌套子元素时仍使用
aria-owns,徒增复杂度。 - 两处
aria-owns均引用同一子元素——辅助技术会任意选择其中一个。 - 忘记焦点顺序与
aria-owns无关:键盘仍按 DOM 的视觉顺序切换焦点,aria-owns仅影响屏幕阅读器遍历无障碍层级的方式。 - 试图借助
aria-owns解决焦点或滚动定位问题——它对两者均无效。 - 将某个区域归属为自身的拥有者,形成循环,破坏树结构。
示例
<!-- Combobox,其弹出层因层叠上下文被传送至 body -->
<div
role="combobox"
id="city-cb"
aria-haspopup="listbox"
aria-expanded="true"
aria-owns="city-listbox"
>
<input type="text" aria-controls="city-listbox" aria-activedescendant="city-opt-2">
</div>
<!-- listbox 位于 body 末尾,语义上归属于 combobox -->
<ul role="listbox" id="city-listbox">
<li role="option" id="city-opt-1">London</li>
<li role="option" id="city-opt-2" aria-selected="true">Paris</li>
</ul>