大多数网站和应用程序都包含 Web 表单。像 DoWebsites<form>
元素中。
HTML <form>
元素 标识了一个文档 地标,其中包含用于提交信息的交互式控件。在 <form>
中嵌套着构成该表单的所有交互式(和非交互式)表单控件。
HTML 非常强大。本节重点介绍 HTML 的强大功能,涵盖 HTML 在不添加 JavaScript 的情况下可以执行的操作。在客户端使用表单数据以某种方式更新 UI 通常涉及 CSS 或 JavaScript,此处不讨论这些内容。有一个完整的学习表单课程。我们不会在此处重复该部分,但我们将介绍几个表单控件以及赋予它们权力的 HTML 属性。
通过表单,您可以让用户与您的网站或应用程序互动,验证输入的信息,并将数据提交到服务器。HTML 属性可以启用要求用户选择表单控件或输入值。HTML 属性可以定义值必须匹配才能有效的特定条件。当用户尝试提交表单时,所有表单控件值都将通过 客户端约束验证,并且可以阻止提交,直到数据与所需条件匹配;所有这些都不需要 JavaScript。您也可以关闭此功能:在 <form>
上设置 novalidate
属性,或者更常见的是在按钮上设置 formnovalidate
,保存表单数据以供稍后完成,从而阻止验证。
提交表单
当用户激活嵌套在表单中的提交按钮时,表单将被提交。当对按钮使用 <input>
时,“value”是按钮的标签,并显示在按钮中。当使用 <button>
时,标签是开始和结束 <button>
标记之间的文本。提交按钮可以通过以下两种方式编写
<input type="submit" value="Submit Form">
<button type="submit">Submit Form</button>
对于非常简单的表单,您需要一个 <form>
元素,其中包含一些表单输入,以及一个提交按钮。但是,提交表单不仅仅如此。
<form>
元素的属性设置了 HTTP 方法,表单通过该方法提交,以及处理表单提交的 URL。是的,表单可以提交、处理,并且可以加载新页面,而无需任何 JavaScript。<form>
元素 就是如此强大。
<form>
元素的 action
和 method
属性值分别定义了处理表单数据的 URL 和用于提交数据的 HTTP 方法。默认情况下,表单数据会发送到当前页面。否则,请将 action
属性设置为应将数据发送到的 URL。
发送的数据由表单的各种表单控件的名称/值对组成。默认情况下,这包括嵌套在表单中且具有 name
的所有表单控件。但是,使用 form
属性,可以包含 <form>
外部的表单控件,并省略嵌套在 <form>
中的表单控件。form
属性在表单控件和 <fieldset>
上受支持,它将与控件关联的表单的 id
作为其值,不一定是控件嵌套在其中的表单。这意味着表单控件不需要物理嵌套在 <form>
中。
method
属性定义了请求的 HTTP 协议:通常是 GET
或 POST
。使用 GET
,表单数据作为 name=value
对的参数字符串发送,附加到 action
的 URL。
使用 POST
,数据将附加到 HTTP 请求的正文中。当发送安全数据(例如密码和信用卡信息)时,请始终使用 POST
。
还有一种 DIALOG
方法。如果 <form method="dialog">
位于 <dialog>
中,则提交表单将关闭对话框;尽管有提交事件,但数据既未清除也未提交。同样,无需 JavaScript。这在 对话框部分中讨论。请注意,由于这不会提交表单,因此您可能需要在提交按钮上同时包含 formmethod="dialog"
和 formnovalidate
。
表单按钮可以具有比本节开头描述的属性更多的属性。如果按钮包含 formaction
、formenctype
、formmethod
、formnovalidate
或 formtarget
属性,则在激活表单提交的按钮上设置的值优先于在 <form>
上设置的 action
、enctype
、method
和 target
。约束验证发生在表单提交之前,但前提是在激活的提交按钮上既没有 formnovalidate
,也没有在 <form>
上设置 novalidate
。
要捕获用于提交表单的按钮,请为按钮指定一个 name
。没有名称或值的按钮不会随表单数据一起在表单提交时发送。
提交表单后
当用户提交已完成的在线表单时,相关表单控件的名称和值将被提交。名称是 name
属性的值。值来自 value
属性的内容或用户输入或选择的值。<textarea>
的值是其内部文本。<select>
的值是选定的 <option>
的 value
,或者,如果 <option>
不包含 value
属性,则该值是选定选项的内部文本。
<form method="GET">
<label for="student">Pick a student:</label>
<select name="student" id="student">
<option value="hoover">Hoover Sukhdeep</option>
<option>Blendan Smooth</option>
<option value="toasty">Toasty McToastface</option>
</select>
<input type="submit" value="Submit Form">
</form>
选择“Hoover Sukhdeep”(或不执行任何操作,因为浏览器默认显示并因此选择第一个选项值),然后单击提交按钮将重新加载此页面,并将 URL 设置为
https://webdev.ac.cn/learn/html/forms?student=hoover
由于第二个选项没有 value
属性,因此内部文本将作为值提交。选择“Blendan Smooth”并单击提交按钮将重新加载此页面,并将 URL 设置为
https://webdev.ac.cn/learn/html/forms?student=Blendan+Smooth
提交表单时,发送的信息包括所有命名的表单控件的名称和值,这些表单控件具有 name
,但未选中的复选框、未选中的单选按钮以及提交表单的按钮以外的任何按钮的名称和值除外。对于所有其他表单控件,如果表单控件具有名称,但未输入或默认值,则表单控件的 name
将随空值一起提交。
有 22 种输入类型,因此我们无法全部介绍。请注意,当您希望用户输入信息时,包含值是可选的,并且通常不是一个好主意。对于用户无法编辑值的 <input>
元素,您应始终包含一个值,包括类型为 hidden
、radio
、checkbox
、submit
、button
和 reset
的输入元素。
为表单控件使用唯一的 name
可以简化服务器端数据处理,并且建议这样做,但复选框和单选按钮是此规则的例外。
单选按钮
如果您曾经注意到,当您选择一组单选按钮中的一个单选按钮时,一次只能选择一个,这是由于 name
属性。这种一次只能选择一个的效果是通过为一组中的每个单选按钮提供相同的 name
来创建的。
name
对于组应该是唯一的:如果您不小心为两个单独的组使用了相同的 name
,则在第二个组中选择单选按钮将取消选择在第一个组中与相同 name
所做的任何选择。
name
以及所选单选按钮的 value
与表单一起提交。确保每个单选按钮都有一个相关的(通常是唯一的)value
。未选中的单选按钮的值不会发送。
您可以在页面上拥有任意数量的单选按钮组,只要每个组都有一个组唯一的 name
,每个组就可以独立工作。
如果您希望在加载页面时选中同一命名组中的一个单选按钮,请包含 checked
属性。即使在用户选择不同的单选按钮时,此单选按钮也将匹配 :default
CSS 伪类。当前选中的单选按钮与 :checked
伪类匹配。
如果用户需要从一组单选按钮中选择一个单选控件,请将 required
属性添加到至少一个控件。在一组单选按钮上包含 required
会使表单提交需要进行选择,但它不一定是具有该属性的单选按钮才能有效。此外,在 <legend>
中清楚地指示 表单控件是必需的。单选按钮组以及每个单独按钮的标签将在稍后描述。
复选框
组中的所有复选框都具有相同的 name
是有效的。只有选中的复选框才将其 name
和 value
与表单一起提交。如果您选中了多个具有相同名称的复选框,则将提交相同的名称(希望具有不同的值)。如果您有多个具有相同名称的表单控件,即使它们并非都是复选框,它们都将被提交,并以与号分隔。
如果您未在复选框上包含 value
,则选中复选框的值将默认为 on
,这可能没有帮助。如果您有三个名为 chk
的复选框,并且它们都被选中,则表单提交将无法破译
https://webdev.ac.cn/learn/html/forms?chk=on&chk=on&chk=on
要使复选框成为必需项,请添加 required
属性。始终告知用户何时必须选中复选框,或何时需要任何表单控件。将 required
添加到复选框只会使该复选框成为必需项;它不会影响具有相同名称的其他复选框。
标签和字段集
为了让用户知道如何填写表单,表单必须是可访问的。每个表单控件都必须有一个标签。您还需要标记表单控件组。虽然单个输入、选择和文本区域使用 <label>
标记,但表单控件组由对它们进行分组的 <fieldset>
的 <legend>
的内容标记。
在前面的示例中,您可能已经注意到,除了提交按钮之外,每个表单控件都有一个 <label>
。标签为表单控件提供可访问的名称。按钮从其内容或值获取其可访问的名称。所有其他表单控件都需要关联的 <label>
。如果没有关联的标签,浏览器仍将呈现您的表单控件,但用户将不知道期望获得哪些信息。
要将表单控件与 <label>
显式关联,请在 <label>
上包含 for
属性:该值是与其关联的表单控件的 id
。
<label for="full_name">Your name</label>
<input type="text" id="full_name" name="name">
将标签与表单控件关联具有多项好处。标签通过为控件提供可访问的名称,使表单控件对屏幕阅读器用户可访问。标签也是“命中区域”;它们通过增加区域使站点对于有灵巧性问题的用户更易于使用。如果您使用的是鼠标,请尝试单击标签“您的姓名”上的任何位置。这样做会使输入获得焦点。
要提供隐式标签,请将表单控件包含在开始和结束 <label>
标记之间。从屏幕阅读器和指针设备的角度来看,这同样是可访问的,但不会像显式标签那样提供样式挂钩。
<label>Your name
<input type="text" name="name">
</label>
由于标签是“命中区域”,因此不要在显式标签中包含交互式元素,也不要在隐式标签中包含除标记的表单控件之外的任何其他交互式组件。例如,如果您在标签中包含链接,虽然浏览器将呈现 HTML,但如果用户单击标签以输入表单控件但被重定向到新页面,则您的用户会感到困惑。
通常,<label>
位于表单控件之前,但在单选按钮和复选框的情况下除外。这不是必需的。这只是常见的 UX 模式。“学习表单”系列具有关于表单设计的信息。
对于单选按钮和复选框组,标签提供与其关联的表单控件的可访问名称;但控件组及其标签也需要一个标签。要标记组,请将所有元素分组到一个 <fieldset>
中,其中 <legend>
为组提供标签。
<fieldset>
<legend>Who is your favorite student?</legend>
<ul>
<li>
<label>
<input type="radio" value="blendan" name="machine"> Blendan Smooth
</label>
</li>
<li>
<label>
<input type="radio" value="hoover" name="machine"> Hoover Sukhdeep
</label>
</li>
<li>
<label>
<input type="radio" value="toasty" name="machine"> Toasty McToastface
</label>
</li>
</ul>
</fieldset>
在此示例中,隐式 <label>
各自标记一个单选按钮,而 <legend>
为单选按钮组提供标签。将 <fieldset>
嵌套在另一个 <fieldset>
中是标准做法。例如,如果表单是对许多问题进行的调查,这些问题分为相关问题组,“最喜欢的学生”<fieldset>
可能嵌套在另一个标记为“您的最爱”的 <fieldset>
中
<fieldset>
<legend>Your favorites:</legend>
<ul start="6">
<li>
<fieldset>
<legend>Who is your favorite student?</legend>
<ul>
<li>
<!-- the rest of the code here -->
这些元素的默认外观导致它们未被充分利用,但 <legend>
和 <fieldset>
可以使用 CSS 进行样式设置。除了所有全局属性外,<fieldset>
还支持 name
、disabled
和 form
属性。当您禁用字段集时,所有嵌套的表单控件都将被禁用。name
和 form
属性在 <fieldset>
上都没有太多用处。name
可用于使用 JavaScript 访问字段集,但字段集本身不包含在提交的数据中(包含在其中的命名表单控件)。
输入类型和动态键盘
如前所述,有 22 种不同的输入类型。在某些情况下,当用户使用动态键盘的设备(例如手机)时,该键盘仅在需要时显示,所使用的输入类型决定了显示的键盘类型。显示的默认键盘可以针对所需的输入类型进行优化。例如,类型 tel
将显示针对输入电话号码优化的键盘;email
包括 @
和 .
;url
的动态键盘包括冒号和斜杠符号。不幸的是,iPhone 仍然没有在 url
输入类型的默认动态键盘中包含 :
。
iPhone 和两款不同的 Android 手机上的 <input type="tel">
的键盘



iPhone 和两款不同的 Android 手机上的 <input type="email">
的键盘



访问麦克风和摄像头
文件输入类型 <input type="file">
允许通过表单上传文件。文件可以是任何类型,由 accept
属性定义和限制。可接受的文件类型列表可以是逗号分隔的文件扩展名列表、全局类型或全局类型和扩展名的组合。例如,accept="video/*, .gif"
接受任何视频文件或动画 gif。声音文件使用“audio/*
”,视频文件使用“video/*
”,图像文件使用“image/*
”。
如果需要使用用户的摄像头或麦克风创建新的媒体文件,则可以使用 媒体捕获规范中定义的枚举 capture
属性。您可以将值设置为 user
以用于面向用户的输入设备,或设置为 environment
以用于手机的后置摄像头或麦克风。通常,使用没有值的 capture
可以正常工作,因为用户将选择他们想要使用的输入设备。
<label for="avatar">A recent photo of yourself:</label>
<input type="file" capture="user" accept="image/*" name="avatar" id="avatar">
内置验证
同样,在不包含任何 JavaScript 的情况下,HTML 可以阻止提交具有无效值的表单。
有一些 CSS 选择器基于 HTML 属性的存在来匹配表单控件,包括 :required
和 :optional
(如果布尔值 required
已设置或未设置);:default
(如果 checked
是硬编码的);以及 :enabled
或 :disabled
,具体取决于元素是否是交互式的以及是否存在 disabled
属性。:read-write
伪类匹配设置了 contenteditable
的元素以及默认情况下可编辑的表单控件,例如 number
、password
和 text
输入类型(但不包括复选框、单选按钮或 hidden
类型等)。如果通常可写元素设置了 readonly
属性,它将匹配 :read-only
。
当用户在表单控件中输入信息时,CSS UI 选择器(包括 :valid
、:invalid
、:in-range
和 :out-of-range
)将根据状态打开和关闭。当用户退出表单控件时,尚未完全支持的 :user-invalid
或 :user-valid
伪类将匹配。
您可以使用 CSS 来提供有关表单控件是否是必需项和有效的提示,因为用户与表单进行交互。您甚至可以使用 CSS 来阻止用户在表单有效之前单击提交按钮
form:invalid [type="submit"] {
opacity: 50%;
pointer-events: none;
}
此 CSS 代码段是一种反模式。虽然您的 UI 可能会感觉直观而清晰,但许多用户尝试提交表单以启用错误消息传递。以这种方式使提交按钮显示为禁用状态不允许进行约束验证,而约束验证是许多用户依赖的功能。
应用的 CSS 会根据 UI 的当前状态不断更新。例如,当您包含具有约束的输入类型(例如 email
、number
、url
和日期类型)时,如果值非空(非空)且当前值不是有效的电子邮件、数字、URL、日期或时间,则 :invalid
CSS 伪类将匹配。这种持续更新与内置 HTML 约束验证不同,后者仅在用户尝试提交表单时发生。
内置约束验证仅与使用 HTML 属性设置的约束相关。虽然您可以根据 :required
和 :valid
/:invalid
伪类设置元素样式,但浏览器提供的错误消息源于基于 required
、pattern
、min
、max
甚至 type
属性的错误,这些错误在表单提交时出现。
当我们尝试在未选择必填的“最喜欢的学生”的情况下提交表单时,约束验证会阻止表单提交,因为出现 validityState.valueMissing
错误。
如果任何 validityState
属性返回 true
,则提交将被阻止,并且浏览器会在第一个不正确的表单控件中显示错误消息,并使其获得焦点。当用户激活表单提交且存在无效值时,第一个无效的表单控件将显示错误消息并获得焦点。如果必填控件未设置值,如果数值超出范围,或者如果值不是 type
属性要求的类型,则表单将不会验证,不会提交,并且将显示错误消息。
如果 number
、日期或时间值低于设置的最小值 min
或高于设置的最大值 max
,则控件将变为 :out-of-range
(和 :invalid
),并且当用户尝试提交表单时,他们将被告知 valididityState.rangeUnderflow
, validityState.rangeOverflow
错误。如果该值与 step
值不一致(无论是否显式设置或默认为 1
),则控件将变为 :out-of-range
(和 :invalid
) 并且会出现 validityState.stepMismatch
错误。该错误以气泡形式出现,默认情况下提供有关如何纠正错误的有用信息。
值的长度也有类似的属性:minlength
和 maxlength
属性将在提交时通过 validityState.tooLong
或 validityState.tooShort
提醒用户错误。maxlength
还可以防止用户输入过多字符。
使用 maxlength
属性可能会导致较差的用户体验。通常,更好的体验是允许用户输入超过允许的字符长度,并提供一个计数器,可以选择 <output>
元素的形式,该元素不会随表单一起提交,从而使用户能够编辑文本,直到输出显示未超过最大允许长度。maxlength
可以包含在您的 HTML 中;与我们讨论的所有内容一样,它无需 JavaScript 即可工作。然后,在加载时,可以使用 maxlength 属性的值在 JavaScript 中创建此字符计数器。
某些输入类型似乎具有默认约束,但实际上并没有。例如,tel
输入类型在具有动态键盘的设备上提供数字电话键盘,但不约束有效值。对于此类型和其他输入类型,可以使用 pattern
属性。您可以指定值需要匹配的正则表达式才能被视为有效。如果值为空字符串,并且该值不是必需的,则不会导致 validityState.patternMismatch
错误。如果为必填项但为空,则会向用户显示 validityState.valueMissing
的默认错误消息,而不是 patternMismatch
。
对于电子邮件,validityState.typeMismatch
对于您的需求来说可能过于宽松。您可能需要包含 pattern
属性,以便不接受没有 TLD 的 Intranet 电子邮件地址作为有效地址。pattern 属性允许提供值必须匹配的正则表达式。当需要模式匹配时,请确保向用户非常清楚地说明期望的内容。
所有这些都可以在不使用单行 JavaScript 代码的情况下完成,但作为 HTML API,您可以使用 JavaScript 在约束验证期间包含自定义消息。您还可以使用 JavaScript 更新剩余字符数、显示密码强度进度条或任何其他多种方式来动态改进完成度。
示例
此示例在 <dialog>
中包含一个表单,该表单具有嵌套的 <form>
,其中包含三个表单控件和两个提交按钮,并带有清晰的标签和说明。
第一个提交按钮关闭对话框。使用 formmethod="dialog"
来覆盖表单的默认方法,并在不提交数据或擦除数据的情况下关闭 <dialog>
。您还必须包含 formnovalidate
,否则浏览器将尝试验证,检查所有必填字段是否都有值。用户可能希望在不输入任何数据的情况下关闭对话框和表单;验证会阻止这种情况。包含 aria-label="close"
,因为“X”是已知的视觉提示,但不是描述性标签。
表单控件都具有隐式标签,因此您无需包含 id
或 for
属性。input 元素都具有 required 属性,使其成为必填项。数字输入显式设置了 step
,以演示如何包含 step
。step
默认为 1
,因此可以省略此属性。
<select>
具有默认值,因此 required
属性是不必要的。value 属性默认设置为内部文本,而不是在每个选项上都包含 value
属性。
末尾的提交按钮将表单的方法设置为 POST。单击后,将检查每个值的有效性。如果所有值都有效,则表单数据将被提交,对话框将关闭,并且页面可能会重定向到 thankyou.php
,这是 action URL。如果缺少任何值,或者数值存在步长不匹配或超出范围,则会显示相关的浏览器定义的错误消息,表单将不会提交,并且对话框将不会关闭。可以使用 validityState.setCustomValidity('message here')
方法自定义默认错误消息。请注意,如果您设置了自定义消息,则必须在一切有效时将消息显式设置为空字符串,否则表单将不会提交。
其他注意事项
有一个专门的部分致力于帮助您的用户在表单中输入正确的数据。为了获得良好的用户体验,重要的是通过包含说明并在必要时提供提示来防止用户出错。虽然本节介绍了 HTML 如何单独提供客户端验证,但验证必须同时在客户端和服务器端进行。可以在表单完成期间以不显眼的方式提供验证,例如在值正确时添加复选标记。但不要在表单控件完成之前提供错误消息。如果用户确实犯了错误,请告知用户错误在哪里以及他们哪里出错了。
当设计表单时,重要的是要记住,世界各地存在不同的姓名标准、地址格式等等。某人的姓氏可能只有一个字母(或者根本没有姓氏),可能没有邮政编码,可能有一个三行街道地址,或者可能没有街道地址。此人可能正在查看您的表单的翻译版本。
表单控件、它们的标签和错误消息应该在屏幕上可见、准确且有意义、可通过程序确定,并且可以通过程序与适当的表单元素或组相关联。autocomplete
属性可以并且应该用于加快表单完成速度并提高可访问性。
HTML 提供了使基本表单控件可访问的所有工具。表单元素或过程的交互性越强,就越需要关注可访问性,包括焦点管理、设置和更新 ARIA 名称、角色和值(在必要时)以及 ARIA 实时公告(在需要时)。但是,正如我们在这里学到的,仅使用 HTML,您就可以在实现可访问性和有效性的目标方面取得很大进展,而无需求助于 ARIA 或 JavaScript。
检查您的理解
测试您对表单的知识。
如何使单选按钮成为同一组的一部分?
name
属性值。id
属性值。哪个 HTML 元素用于告诉用户此表单字段的用途?
<label>
<h1>
<title>