HTML 结构设计与语义
基本语法与字段集(Fieldset)的使用
在 HTML 中,单选按钮通过 input 元素,类型设为 radio,并且同一组的单选按钮通过 name 属性保持一致,以确保仅有一个被选中。为了提升可点击性,可以为每个单选按钮提供与之关联的 label 标签,且通过 id 与 for 属性建立关联。
要把相关选项放在一个可访问的分组中,通常使用 fieldset 与 legend 来提供分组语义和说明,辅助屏幕阅读器更好地朗读内容。
<!-- 基本单选按钮组示例 -->
<form><fieldset><legend>性别</legend><div><input type="radio" id="g_m" name="gender" value="male" /><label for="g_m">男</label></div><div><input type="radio" id="g_f" name="gender" value="female" /><label for="g_f">女</label></div><div><input type="radio" id="g_o" name="gender" value="other" /><label for="g_o">其他</label></div></fieldset>
</form>
通过上述结构,name 的一致性确保同组只有一个被选中,而 id 与 label 的配对则扩大了点击区域,提高用户体验。

标签关联与可点击区域
为了实现更好的可访问性,建议将 input 与 label 直接关联,方法是给 input 设置 id,再用 label 的 for 指向该 id,从而点击文字也能选中相应的单选按钮。
另外一种写法是将 input 嵌套在 label 内部,这同样可以扩大可点击区域,并减少额外标签的数量,适用于简单的表单布局。
<!-- 标签关联示例(两种写法) -->
<form><div><input type="radio" id="r1" name="choice" value="1" /><label for="r1">选项1</label></div><div><label><input type="radio" name="choice" value="2" />选项2</label></div>
</form>
在无障碍体验中,确保所有单选按钮都具备 name、id、以及清晰的文本标签,以便屏幕阅读器正确朗读当前选项和分组信息。
样式与无障碍设计
使用 aria 与无障碍最佳实践
尽管原生的 input type="radio" 已经具备良好的无障碍性,但在自定义控件或复杂表单场景中,添加适当的 ARIA 属性仍然是必要的。为分组提供 aria-labelledby 指定的标签,或使用 aria-label 为每个选项提供可读文本。
在自定义外观的情况下,保持原生控件在键盘导航中的行为很重要,确保 tabindex、focus 样式与 Enter/Space 键切换逻辑一致,避免不可预期的可访问性问题。
<!-- 使用 aria 标签的示例 -->
<form aria-label="性别选择"><fieldset><legend>性别</legend><input type="radio" id="ra1" name="gender" value="m" aria-labelledby="lb_m" /><label id="lb_m" for="ra1">男</label><input type="radio" id="ra2" name="gender" value="f" aria-labelledby="lb_f" /><label id="lb_f" for="ra2">女</label></fieldset>
</form>
使用 aria-label 或 aria-labelledby 可以在视觉隐藏或样式化时仍提供给屏幕阅读器可用的文本信息,提升无障碍性。
自定义外观的实现要点
为达到美观的 UI 效果,可以隐藏原生单选按钮的默认外观,改用自定义样式,但需要保证 input 仍然可聚焦,以保持键盘操作可用性。
常见做法是将 input 的显示设为隐藏,使用一个自定义的圆圈来显示选中状态,通过 ::before 或 ::after 伪元素实现视觉效果,同时保留原生控件以保证屏幕阅读器读取值。
/* 保留无障碍,隐藏原生外观,绘制自定义圆圈 */
input[type="radio"].custom {appearance: none;-webkit-appearance: none;width: 16px;height: 16px;border-radius: 50%;border: 2px solid #555;display: inline-block;vertical-align: middle;margin-right: 6px;
}
input[type="radio"].custom:checked {background: #2a9df4;border-color: #2a9df4;
}
input[type="radio"].custom:checked::after {content: '';display: block;width: 8px; height: 8px;margin: 3px;border-radius: 50%;background: #fff;
}
重要的是测试在不同浏览器与设备上的渲染差异,确保自定义样式不会破坏 无障碍性,且在聚焦时能清晰地呈现焦点样式。
交互与表单提交
事件处理与数据获取
在表单提交前,通过 name 属性来获取被选中的值,常见做法是查询 input[name="..."] 的 :checked 伪类或 JavaScript 的 checked 属性。
对于表单校验,可以在提交时检查是否存在任意一个被选中的单选按钮,以及在不可选时给出可访问的错误信息。
// 获取选中的单选按钮值
const gender = document.querySelector('input[name="gender"]:checked');
const value = gender ? gender.value : null;// 提交前校验示例
document.querySelector('form').addEventListener('submit', e => {if (!value) {e.preventDefault();// 显示无障碍提示alert('请先选择一个选项');}
});
使用 name、value、checked,可以在服务器端接收到 gender 的选择结果,方便后端处理。
示例与测试步骤
要验证实现步骤的正确性,可按以下测试流程:在浏览器中打开页面,使用鼠标或键盘切换单选按钮,观察 聚焦状态、选中状态 的变化,以及提交后服务器端收到的 name 与 value。
记录关键要点,如 aria-label 是否在无障碍工具中被正确朗读,fieldset 与 legend 的描述是否清晰。


