先记住这个答案
fieldset 和 legend 解决“这几个输入一起回答什么”的问题。把同一题的单选或复选项放入 <fieldset>,在第一个 <legend> 写组标题,再给每个控件配自己的 <label>。这样不仅有视觉边框,辅助技术也能把组名与各控件名称联系起来。
fieldset表达控件之间的分组- 首个
legend是组标题 - 每个输入仍需要自己的
label - 组标题不该由占位文字代替
单选组为什么需要一个总问题
如果页面只列“快递”“自提”两个单选标签,读屏用户进入选项时可能不知道这组选项属于配送方式、领取方式还是退款方式。legend 提供整个选择题的题干,而 label 提供单个答案。两者不能互相替代。
<fieldset>
<legend>配送方式</legend>
<label><input type="radio" name="delivery" value="ship">快递</label>
<label><input type="radio" name="delivery" value="pickup">自提</label>
</fieldset>两枚单选按钮共用 name,浏览器将它们作为互斥选项;fieldset 则补足分组语义。虽然视觉上可能已有标题,但若用普通段落代替 legend,辅助技术未必按同样方式把标题与整组控件关联。
组名与控件名各管哪一层
legend 最适合写一组控件共同回答的问题,如“联系偏好”;每个 label 则写“邮件”“短信”等具体选项。占位文字会在输入后消失,也不是可靠的控件名称,尤其不能代替组名。
fieldset 还可以用 disabled 一次禁用一组控件,其中首个 legend 内的表单控件有例外。若页面有层层嵌套的分组,读屏输出可能变得冗长,应只在确有独立问题层级时嵌套,并保持标题短而清楚。
例如收货地址里有“联系人”“电话”“邮编”三个输入,逐个 <label> 只能告诉用户每个框是什么,不能说明它们共同属于“新的收货地址”。<legend> 是这组问题的名字,屏幕阅读器进入组内控件时可以结合组名建立上下文。一个页面有多组相同的“姓名”输入时,这个差别尤其明显:没有组名,用户很难知道当前读到的是收货人还是发票联系人。
容易答错的地方
- 给组写了
legend就不给各输入标签 - 用户还需要知道当前具体选项是什么,单个控件仍需自己的
label。 - 只用 CSS 边框和标题模拟分组
- 视觉相似不代表有同样的表单语义;相关控件应使用真实的分组元素。
面试官还会怎么问?
所有输入都要套 fieldset 吗?
不必。它适合有共同问题的一组控件,单个普通字段用 label 通常已足够。
legend 应放在什么位置?
通常作为 <fieldset> 的第一个子元素;首个组名提供该分组标题。
fieldset 会改变单选按钮互斥规则吗?
互斥主要由相同表单中的 name 决定,字段集负责语义分组。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。