我们早在之前的文章中就遇见过它了。
警告:
严禁在一个表单内嵌套另一个表单。嵌套会导致表单出现不可预测的行为。
在
下面我们来介绍一下嵌套在表单中的结构元素。
许多辅助技术在使用 元素时,会将其视为相应
这里有一个小例子:
html
Fruit juice size
Small
Medium
Large
备注:
你可以在 fieldset-legend.html(也可以查看在线示例)中看到该例。
当阅读上述表格时,屏幕阅读器将会为第一个微件读出“Fruit juice size small”,“Fruit juice size medium”为第二个,“Fruit juice size large”为第三个。
本例中的用例是最重要的。每当使用一组单选按钮时,都应该将它们嵌套在
因为它对辅助技术的影响,
元素
正如我们在前一篇文章中看到的, 元素是为 HTML 表单微件定义标签的正式方法。如果你想构建无障碍的表单,这是最重要的元素——当实现的恰当时,屏幕阅读器会连同有关的说明和表单元素的标签一起朗读。以我们在上一篇文章中看到的例子为例:
htmlName:
当 标签正确地通过 for 属性与 相关联(for 属性包含相应 元素的 id 属性)时,屏幕阅读器会读出诸如“Name, edit text”之类的东西。
还有另一种方法可以将表单控件与标签关联起来——将表单控件嵌套在 中,隐式地将其关联起来。
Name:
不过,即使在这种情况下,最佳做法也是设置 for 属性,以确保所有辅助技术都能理解标签和微件之间的关系。
如果没有设置标签,或者表单控件既没有隐式关联标签,也没有显式关联标签,屏幕阅读器只会读出“编辑”之类的东西,这样会没什么帮助。
标签也可点击!
正确设置标签的另一个好处是可以在所有浏览器中单击标签来激活相应的微件。这对于像文本输入这样的例子很有用,这样你可以通过点击标签,和点击输入区效果一样,来聚焦于它,这对于单选按钮和复选框尤其有用——这种控件的可点击区域可能非常小,设置标签来使它们可点击区域变大是非常有用的。
例如,点击下面示例中的“I like cherry”标签文本,就会切换 taste_cherry 复选框的选定状态:
I like cherry
I like banana
你可以在 checkbox-label.html(也可以查看在线示例)中看到该例。
多个标签
严格地说,你可以在单个微件上放置多个标签,但是这不是一个好主意,因为一些辅助技术可能难以处理它们。在多个标签的情况下,你应该将微件和它的标签嵌套在一个 元素中。
让我们考虑下面这个例子:
必填字段后随 *。
名字:*
顶部的段落定义了必填元素的规则。该规则必须在使用之前列入,以便视力正常的用户和屏幕阅读器等辅助技术的用户在遇到必填元素之前就能了解其含义。虽然这有助于告知用户星号的含义,但不能依赖它。屏幕阅读器在遇到星号时会将其说成“星号”。当视力正常的鼠标用户悬停鼠标时,应显示“必须”,这可以通过使用 title 属性来实现。标题是否被朗读取决于屏幕阅读器的设置,因此同时包含 aria-label 属性更为可靠,屏幕阅读器始终会读取该属性。
上述变体的效果会随着时间的推移而增强:
在第一个例子中,标签根本没有和 input 一起被念出来——读出来的只是“编辑”和单独被念出的标签。多个 元素会混淆屏幕阅读器。
在第二个例子中,稍微显得清晰一点了——标签和输入一起,读出的是“名字 星号 名字 编辑 必须”,但标签仍然是单独读出的。这还是有点令人困惑,但这次还是稍微好一点了,因为 和 label 联系起来了。
第三个例子是最好的——实际标签是一起读出的,标签和输入读出的是“名字 必须 编辑 必须”。
你可能会得到一些不同的结果,这取决于你的屏幕阅读器。这是在 VoiceOver 上测试的(NVDA 的行为也类似)。我们也乐于听听你的试验结果。
你可以在 GitHub 上看到 required-labels.html(也可以查看在线示例)。不要运行 2 个或 3 个未注释版本的示例——如果你有多个标签和多个输入相同的 ID,那么屏幕阅读器肯定会感到困惑!
用于表单的通用 HTML 结构
除了特定于 HTML 表单的结构之外,还应该记住表单同样是 HTML。这意味着你可以使用 HTML 的所有强大功能来构造一个 HTML 表单。
正如你在示例中可以看到的,通常的做法是用
和
除了
最重要的是,要找到一种舒适的编码风格,使表单易于访问和使用。每个独立的功能部分都应包含在一个单独的 元素中, 元素包含单选按钮。
动手练习:构建一个表单结构
让我们把这些想法付诸实践,建立一个稍微复杂一点的表单结构——一个支付表单。这个表单将包含许多你可能还不了解的微件类型——现在不要担心这个,在下一篇文章(基本的原生表单控件)中,你将了解它们是如何工作的。现在,当你遵循下面的指令时,请仔细阅读这些描述,并开始理解我们使用的包装器元素是如何构造表单的,以及为什么这么做。
在开始之前,在计算机上的一个新目录中,创建一个空白模板文件的本地副本。
接下来,通过添加
必需的字段已使用 * 标示。
接下来,我们将在表单中添加一个更大的代码段,在我们之前的代码下面。在这里,你将看到,我们正在将联系人信息字段包装在一个单独的 元素中。此外,我们有一组三个单选按钮,每个单选按钮都放在自己的列表中()元素。最后,我们有两个标准文本 和它们相关的 元素,每个元素包含在 中,加上密码输入。现在将这些代码添加到你的表单中: html 联系人信息
中,加上密码输入。现在将这些代码添加到你的表单中:
称号
Ace
King
Queen
名字:
*
邮箱:
密码:
表单的第二个 是支付信息。在这里,我们有三个不同的微件以及它们的标签,每个都包含在 中。第一个是选择信用卡类型的下拉菜单()。第二个是 tel 类型的 元素,用于输入信用卡号码;虽然我们可以使用 number 类型,但我们不需要数字的旋转 UI。最后一个是 text 类型的 元素,用于输入卡片的到期日期;其中包括 placeholder 属性,用于指示正确的格式,以及 pattern 属性,用于测试输入的日期是否具有正确的格式。这些更新的输入类型在 HTML5 输入类型中重新引入。在上一节下方输入以下内容: html 付款信息
中。第一个是选择信用卡类型的下拉菜单()。第二个是 tel 类型的 元素,用于输入信用卡号码;虽然我们可以使用 number 类型,但我们不需要数字的旋转 UI。最后一个是 text 类型的 元素,用于输入卡片的到期日期;其中包括 placeholder 属性,用于指示正确的格式,以及 pattern 属性,用于测试输入的日期是否具有正确的格式。这些更新的输入类型在 HTML5 输入类型中重新引入。在上一节下方输入以下内容:
信用卡类型
Visa
Mastercard
American Express
卡号:
到期日:
type="text"
id="expiration"
name="expiration"
required
placeholder="MM/YY"
pattern="^(0[1-9]|1[0-2])\/([0-9]{2})$" />
我们要添加的最后一个部分要简单得多,它只包含了一个 submit 类型的 ,用于提交表单数据。现在把这个添加到表单的底部:
验证付款请求
最后,通过添加
h1 {
margin-top: 0;
}
ul {
margin: 0;
padding: 0;
list-style: none;
form {
margin: 0 auto;
width: 400px;
padding: 1em;
border: 1px solid #ccc;
border-radius: 1em;
div + div {
margin-top: 1em;
label span {
display: inline-block;
text-align: right;
input,
textarea {
font: 1em sans-serif;
width: 250px;
box-sizing: border-box;
border: 1px solid #999;
input[type="checkbox"],
input[type="radio"] {
width: auto;
border: none;
input:focus,
textarea:focus {
border-color: #000;
vertical-align: top;
height: 5em;
resize: vertical;
fieldset {
button {
margin: 20px 0 0 0;
label {
position: relative;
p label {
width: 100%;
label em {
position: absolute;
right: 5px;
top: 20px;
我们在下面完成的表单中应用了一些额外的 CSS。如果你想更改表单的外观,可以复制示例中的样式,或者访问为 web 表单添加样式。
技能测试!
本文已经结束,但你还记得最重要的信息吗?在继续阅读之前,可以找到进一步的测试来验证是否记住了这些信息——请参见技能测试:表格结构。
总结
现在,你已经掌握了正确构建 web 表单所需的全部知识。我们将在接下来的几篇文章中介绍这里介绍过的许多功能,下一篇文章将更详细地介绍如何使用所有不同类型的表单部件来收集用户信息。
参见
A List Apart: 合理的表单:表单可用性检查清单
上一页 概述:Web 表单构建块 下一页
进阶内容
如何构建自定义表单控件
使用 JavaScript 发送表单
表单微件兼容性列表
Help improve MDN
Was this page helpful to you?
Yes
No
Learn how to contribute
This page was last modified on 2025年7月11日 by MDN contributors.
View this page on GitHub • Report a problem with this content