如何构建 Web 表单
在掌握了基础知识之后,我们将更详细地了解用于为表单的不同部分提供结构和含义的元素。
| 预备知识 | 对 HTML 的基本理解。 |
|---|---|
| 目标 | 了解如何构建 HTML 表单并赋予它们语义,使其可用且易于访问。 |
表单的灵活性使其成为 HTML 中最复杂的结构之一;您可以使用专用表单元素和属性构建任何类型的基本表单。在构建 HTML 表单时使用正确的结构将有助于确保表单既可用又易于访问。
<form> 元素
<form> 元素正式定义了表单和决定表单行为的属性。每次您想要创建 HTML 表单时,都必须使用此元素开始,并将所有内容嵌套在其中。许多辅助技术和浏览器插件可以发现 <form> 元素并实现特殊的钩子,使其更易于使用。
我们已经在上一篇文章中遇到了这个。
警告: 严禁将一个表单嵌套在另一个表单中。嵌套可能导致表单行为不可预测,因此这是一个糟糕的主意。
总是可以在 <form> 元素之外使用表单控件。如果您这样做,默认情况下,该控件与任何表单无关,除非您使用其 form 属性将其与表单关联。引入此功能是为了让您即使在表单控件未嵌套在表单中时也能显式地将其与表单绑定。
让我们继续并介绍您会在表单中找到的结构元素。
<fieldset> 和 <legend> 元素
<fieldset> 元素是一种方便的方式,可以创建具有相同目的的小部件组,以实现样式和语义目的。您可以通过在开放 <fieldset> 标签下方包含一个 <legend> 元素来标记 <fieldset>。<legend> 的文本内容正式描述了其所包含的 <fieldset> 的目的。
许多辅助技术会将 <legend> 元素视为对应 <fieldset> 元素内每个控件标签的一部分。例如,一些屏幕阅读器,如 Jaws 和 NVDA,会在朗读每个控件的标签之前朗读图例的内容。
这里有一个小例子
<form>
<fieldset>
<legend>Fruit juice size</legend>
<p>
<input type="radio" name="size" id="size_1" value="small" />
<label for="size_1">Small</label>
</p>
<p>
<input type="radio" name="size" id="size_2" value="medium" />
<label for="size_2">Medium</label>
</p>
<p>
<input type="radio" name="size" id="size_3" value="large" />
<label for="size_3">Large</label>
</p>
</fieldset>
</form>
注意: 您可以在 fieldset-legend.html 中找到此示例(也可以在线查看)。
在阅读上面的表单时,屏幕阅读器会为第一个小部件朗读“果汁尺寸小”,为第二个朗读“果汁尺寸中”,为第三个朗读“果汁尺寸大”。
此示例中的用例是最重要的用例之一。每次您有一组单选按钮时,都应将其嵌套在 <fieldset> 元素中。还有其他用例,通常 <fieldset> 元素也可以用于分隔表单。理想情况下,长表单应分布在多个页面上,但如果表单很长并且必须在单个页面上,则将不同的相关部分放在不同的 fieldset 中可以提高可用性。
由于其对辅助技术的影响,<fieldset> 元素是构建可访问表单的关键元素之一;但是,您有责任不要滥用它。如果可能,每次构建表单时,尝试听屏幕阅读器如何解释它。如果听起来很奇怪,请尝试改进表单结构。
<label> 元素
正如我们在上一篇文章中看到的,<label> 元素是为 HTML 表单小部件定义标签的正式方式。如果您想构建可访问的表单,这是最重要的元素——如果实施得当,屏幕阅读器将朗读表单元素的标签以及任何相关说明,并且它对视力正常的用户也很有用。以下是我们上一篇文章中看到的示例
<label for="name">Name:</label> <input type="text" id="name" name="user_name" />
通过其 `for` 属性(包含 `<input>` 元素的 `id` 属性)将 `<label>` 与 `<input>` 正确关联后,屏幕阅读器将朗读“姓名,编辑文本”之类的内容。
还有另一种将表单控件与标签关联的方法 — 将表单控件嵌套在 `<label>` 中,从而隐式关联它。
<label for="name">
Name: <input type="text" id="name" name="user_name" />
</label>
然而,即使在这种情况下,最佳实践是设置 `for` 属性,以确保所有辅助技术都能理解标签和控件之间的关系。
如果没有标签,或者如果表单控件既没有隐式也没有显式地与标签关联,屏幕阅读器将朗读“编辑空白文本”之类的东西,这根本没有帮助。
标签也可以点击!
正确设置标签的另一个优点是,您可以单击或轻触标签以激活相应的控件。这对于文本输入等控件很有用,您可以单击标签和输入来使其获得焦点,但它对于单选按钮和复选框尤其有用——此类控件的点击区域可能非常小,因此尽可能使其易于激活很有用。
例如,点击下面示例中“我喜欢樱桃”的标签文本将切换 _taste_cherry_ 复选框的选中状态
<form>
<p>
<input type="checkbox" id="taste_1" name="taste_cherry" value="cherry" />
<label for="taste_1">I like cherry</label>
</p>
<p>
<input type="checkbox" id="taste_2" name="taste_banana" value="banana" />
<label for="taste_2">I like banana</label>
</p>
</form>
注意: 您可以在 checkbox-label.html 中找到此示例(也可以在线查看)。
多个标签
严格来说,您可以在单个控件上放置多个标签,但这并不是一个好主意,因为某些辅助技术可能难以处理它们。在有多个标签的情况下,您应该将控件及其标签嵌套在一个 <label> 元素中。
让我们考虑这个例子
<p>Please complete all required (*) fields.</p>
<!-- So this: -->
<!--<div>
<label for="username">Name:</label>
<input id="username" type="text" name="username" required />
<label for="username">*</label>
</div>-->
<!-- would be better done like this: -->
<!--<div>
<label for="username">
<span>Name:</span>
<input id="username" type="text" name="username" required />
<span>*</span>
</label>
</div>-->
<!-- But this is probably best: -->
<div>
<label for="username">Name *:</label>
<input id="username" type="text" name="username" required />
</div>
顶部的段落说明了必填元素的规则。该规则必须在使用之前包含,以便视力正常的用户和屏幕阅读器等辅助技术 (AT) 用户可以在遇到必填元素之前了解其含义。
与表单一起使用的常见 HTML 结构
除了特定于 Web 表单的结构之外,记住表单标记只是 HTML 也很重要。这意味着您可以使用 HTML 的所有功能来构建 Web 表单。
正如您在示例中看到的,将标签及其控件包装在 <ul> 或 <ol> 列表中的 <li> 元素中是一种常见做法。<p> 和 <div> 元素也常被使用。建议使用列表来构建多个复选框或单选按钮。
除了 <fieldset> 元素之外,使用 HTML 标题(例如,h1、h2)和分段(例如,<section>)来构建复杂表单也是常见做法。
最重要的是,您需要找到一种舒适的编码风格,以创建可访问、可用的表单。每个独立的功能部分都应包含在单独的 <section> 元素中,并使用 <fieldset> 元素来包含单选按钮。
构建表单结构
让我们将这些想法付诸实践,构建一个稍微复杂一点的表单——一个支付表单。这个表单将包含许多您可能还不理解的控件类型。暂时不用担心这些;您将在下一篇文章(基本原生表单控件)中了解它们的工作原理。现在,请仔细阅读描述,按照下面的说明操作,并开始了解我们正在使用哪些包装元素来构建表单,以及为什么。
-
首先,在您的计算机上的新目录中,将我们的空白模板文件复制到本地。
-
接下来,通过添加
<form>元素来创建表单html<form> -
在
<form>元素内部,添加一个标题和段落,告知用户必填字段是如何标记的html<h1>Payment form</h1> <p>Please complete all required (*) fields.</p> -
接下来,我们将在表单中,在之前输入的下方,添加一个更大的代码段。在这里您会看到我们将联系信息字段包装在一个单独的
<section>元素中。此外,我们有一组三个单选按钮,每个按钮都放在自己的列表 (<li>) 元素中。我们还有两个标准文本<input>及其关联的<label>元素,每个都包含在一个<p>中,以及一个用于输入密码的密码输入。将此代码添加到您的表单中html<section> <h2>Contact information</h2> <fieldset> <legend>Title</legend> <ul> <li> <label for="title_1"> <input type="radio" id="title_1" name="title" value="A" /> Ace </label> </li> <li> <label for="title_2"> <input type="radio" id="title_2" name="title" value="K" /> King </label> </li> <li> <label for="title_3"> <input type="radio" id="title_3" name="title" value="Q" /> Queen </label> </li> </ul> </fieldset> <p> <label for="name">Name *:</label> <input type="text" id="name" name="username" required /> </p> <p> <label for="mail">Email *:</label> <input type="email" id="mail" name="user-mail" required /> </p> <p> <label for="pwd">Password *:</label> <input type="password" id="pwd" name="password" required /> </p> </section> -
表单的第二个
<section>是支付信息。我们有三个不同的控件及其标签,每个都包含在一个<p>中。第一个是用于选择信用卡类型的下拉菜单 (<select>)。第二个是tel类型的<input>元素,用于输入信用卡号;虽然我们可以使用number类型,但我们不希望使用数字的微调器 UI。最后一个是text类型的<input>元素,用于输入卡的有效期;这包括一个指示正确格式的 placeholder 属性,以及一个测试输入日期是否具有正确格式的 pattern。HTML5 输入类型中重新介绍了这些较新的输入类型。在上一节下方输入以下内容
html<section> <h2>Payment information</h2> <p> <label for="card"> <span>Card type:</span> </label> <select id="card" name="user-card"> <option value="visa">Visa</option> <option value="mc">Mastercard</option> <option value="amex">American Express</option> </select> </p> <p> <label for="number">Card number *:</label> <input type="tel" id="number" name="card-number" required /> </p> <p> <label for="expiration">Expiration date *:</label> <input type="text" id="expiration" name="expiration" required placeholder="MM/YY" pattern="^(0[1-9]|1[0-2])\/([0-9]{2})$" /> </p> </section> -
我们将添加的最后一节要简单得多,只包含一个
submit类型的<button>,用于提交表单数据。现在将其添加到表单底部html<section> <p> <button type="submit">Validate the payment</button> </p> </section> -
最后,通过添加外部
<form>结束标签来完成您的表单html</form>
我们在下面完成的表单中应用了一些额外的 CSS。如果您想更改表单的外观,可以从示例中复制样式,或访问样式化 Web 表单。
总结
您现在拥有了正确构建 Web 表单所需的所有知识。我们将在接下来的几篇文章中介绍这里介绍的许多功能,下一篇文章将更详细地探讨如何使用所有不同类型的表单控件来收集用户的信息。