标准 · ARIA

角色 复合控件

listbox

将元素标记为可选选项的列表。简单的单选场景请使用 <select>——原生元素提供适合移动端的选择器与完整的键盘支持。仅在需要自定义样式、带自定义渲染的多选功能,或与组合框配合使用时,才使用 role="listbox"。

使用时机

尽可能使用 <select>(单选)或 <select multiple>(多选)。原生元素提供完整的交互模型,包括符合平台规范的键盘处理。

以下情况适合使用 role="listbox"

  • 列表框作为自定义组合框的弹出层。
  • 需要富选项内容(图标、辅助文字),而 <select> 无法渲染。
  • 需要带自定义勾选样式的多选功能。
  • 构建穿梭框或可过滤的选择器。

子元素必须为 role="option"(允许使用 role="group" 作为分组的中间层包装)。多选列表框需设置 aria-multiselectable="true"

键盘与焦点规范

参见 APG 列表框模式

  • Tab 将焦点移入列表框;再次 Tab 移出。列表框内部,焦点保持在容器上,“活动”选项通过 aria-activedescendant 追踪。
  • 上下方向键移动活动选项。
  • Home / End 跳转到第一个 / 最后一个选项。
  • 单选:每次按方向键同时选中活动选项。
  • 多选:Space 切换活动选项的选中状态;Shift+方向键扩展连续区域;Ctrl/Cmd+A 全选。
  • 输入预测:输入字母跳转到下一个以该字母开头的选项。

常见错误

  • 将 DOM 焦点移至每个选项,而非使用 aria-activedescendant。这会导致输入预测和组合框集成失效。
  • role="option" 子元素缺少 id 属性——aria-activedescendant 无法引用它们。
  • 多选列表框未设置 aria-multiselectable="true"。屏幕阅读器会将其宣读为单选。
  • 列表框拥有位于 DOM 其他位置的选项,却未使用 aria-owns 明确关联关系。
  • 对只读静态列表使用 role="listbox"。那应该是 role="list" 而非 listbox——listbox 隐含交互性。

示例

<label id="topicsLabel">选择您的主题</label>
<ul
  role="listbox"
  aria-labelledby="topicsLabel"
  aria-multiselectable="true"
  tabindex="0"
  aria-activedescendant="topic-1"
>
  <li id="topic-1" role="option" aria-selected="true">无障碍</li>
  <li id="topic-2" role="option" aria-selected="false">辅助技术</li>
  <li id="topic-3" role="option" aria-selected="true">标准规范</li>
</ul>