角色 控件
radio
将元素标记为互斥选项组中的单个选项。radio 必须置于 radiogroup(或原生 fieldset)内。优先使用 <input type="radio">;仅当无法使用原生输入框时,才考虑 role="radio"。
使用场景
使用 <input type="radio">,通过共同的 name 属性分组,并置于带有 <legend> 的 <fieldset> 中。原生元素可免费提供方向键导航、游走式 tabindex、互斥选择及表单提交功能。
role="radio" 适用于自定义组件——分段控件、评分组件、主题化选择器——即无法使用原生输入框的场景。带有 role="radio" 的元素必须拥有一个 role="radiogroup" 的父元素(或 aria-owns 目标)。
键盘与焦点规范
根据 APG 单选组模式:
- Tab 键将焦点移入组内,落在已选中的单选按钮上(若无选中项,则落在第一个单选按钮)。
- Tab 键将焦点移出该组。Tab 不在各单选按钮之间循环。
- 方向键(上/下或左/右)将焦点移至相邻单选按钮,并同时选中该项。这与常规不同——多数组件将焦点与选中状态分离,而单选按钮将二者耦合。
- 空格键选中当前获焦的单选按钮(若尚未选中)。
采用游走式 tabindex:仅当前选中的单选按钮设为 tabindex="0",其余设为 tabindex="-1"。
常见错误
- 自定义单选按钮通过 Tab 键在各选项间循环(而非使用方向键),破坏了标准的单选交互模型。
role="radio"缺少外层role="radiogroup"。屏幕阅读器无法播报组标签及当前项在组中的位置。- 所有单选按钮均设为
tabindex="0"——每个按钮都进入 Tab 顺序,大幅增加按键次数。 - 初始渲染时缺少
aria-checked。 - 自定义单选按钮在重复点击时取消选中。单选按钮具有互斥性:一旦选中,只能通过选中同组其他项来取消选中。
示例
<!-- 推荐用法 -->
<fieldset>
<legend>通知频率</legend>
<label><input type="radio" name="freq" value="daily" checked> 每天</label>
<label><input type="radio" name="freq" value="weekly"> 每周</label>
<label><input type="radio" name="freq" value="never"> 从不</label>
</fieldset>
<!-- 自定义单选组 -->
<div role="radiogroup" aria-labelledby="freqLabel">
<span id="freqLabel">通知频率</span>
<div role="radio" aria-checked="true" tabindex="0">每天</div>
<div role="radio" aria-checked="false" tabindex="-1">每周</div>
<div role="radio" aria-checked="false" tabindex="-1">从不</div>
</div>