在创建HTML表单时,最重要的一件事就是如何用正确的方式构建它。而之因此重要,缘由有二:一是保证表单能被正确使用、二是这能保证你的表单是无障碍的(能够被能力不一样的人使用)。而正因HTML表单的无障碍性很重要,故在本文中咱们将了解如何使一个表单无障碍,这并不很难、只是有几个技巧须要你了解下。java
表单的灵活性决定了它们是HTML中最复杂的结构。经过使用专门的表单元素和属性,咱们能够创建任何形式的表单。也确实有过一些更丰富多彩的脚本技术如XForms(现已过期),但很不幸这些表单技术并未被各大浏览器普遍应用。所以,咱们每每得依赖Javascript来处理表单;但在本文中,咱们只会详细讨论如何使用表单元素,若你想知道如何构建自定义表单组件,可参阅[怎样建立定制表单组件]()。web
<form>
元素是用来正式定义表单的元素,其属性决定了表单会有什么行为。当你想要创建一个HTML表单时,就必须以该元素开头。不少无障碍技术或浏览器插件可以检测到<form>
元素,同时他们也实现了特殊的方式来让表单更易于使用。segmentfault
注:严禁把一个form元素嵌套在另外一个里边。那样会致使不可预知的行为,具体取决于用户使用了何种浏览器。浏览器
<form>
元素支持下列属性,它们全是可选的:服务器
<form>
元素的属性app
属性名 | 默认值 | 描述 |
---|---|---|
accept-charset | UNKNOWN | 一个空格分隔或逗号分隔的列表(HTML5中,只有空格可做为分隔符。),这个列表包括了服务器支持的字符编码。浏览器以这些编码被列举的顺序使用它们。默认值是一个保留字符串“UNKNOWN”。这个字符串指的是和包含这个form元素的文档使用相同的编码。 |
action | 处理这个表单所提交信息的程序所在的URL。 | |
autocomplete | on | 指示表单组件是否可以拥有被浏览器自动补全的默认值。该属性共有两个可选值:on 或off 。 |
enctype | application/x-www-form-urlencoded | 当 method 属性值为 post 时, enctype 是提交form给服务器的内容的 MIME 类型 。可能的取值有:application/x-www-form-urlencoded (默认值)、multipart/form-data (用于一个 type 属性设置为 "file" 的<input> 元素)、text/plain (HTML5)。 |
method | get | 浏览器使用这种 HTTP 方式来提交 form。可能的值有:post、get。 |
name | 这个form的名字。一个文档中的多个form当中,name必须惟一而不只仅是一个空字符串。做为替代,最好使用id 。 |
|
novalidate | (false) | 这个布尔类型的属性指示了,当提交时form是否没有被验证。 |
target | _self | 用一个关键字指示在何处展现提交表单后收到的响应,展现的地方能够是<iframe> 、标签页、浏览器窗口等;下面是该属性几个可能的值:_self (把响应加载到同一浏览器环境(<iframe> 、标签页、浏览器窗口等))、_blank (把响应加载到一个新的浏览器环境)、_parent (把响应加载到父级浏览器环境,若无父级环境则和_self 一致)、_top (把响应加载到最顶层的浏览器环境(即已无父环境的浏览器环境),若无父级环境则和_self 一致) |
要注意的是,可能你会常常在<form>
元素外使用表单组件,而这样作的话这些组件就和任何表单都没有关系了。虽然这些表单组件确实能够用在表单以外,但如此一来你就得给它们设定好用途了,毕竟它们单独使用时是没有特殊效果的,你必须用Javascript来自定义。dom
从技术上讲,HTML5已经引进了一个form
属性给各个表单元素,该属性能让你明确绑定一个元素和一个表单,即便元素再也不<form>
的内部。然而很遗憾,该特性的跨浏览器实现暂时还没能让人以为它是可靠的。ide
<fieldset>
元素能够很方便地用于建立一组具备相同目的的组件。一个<fieldset>
元素能够被一个<legend>
元素所标记,<legend>
元素用于明确地描述<fieldset>
元素的目的。许多无障碍技术会使用<legend>
元素做为<fieldset>
元素内各组件label的一部分。例如,某些屏幕阅读器如jaws或NVDA会在读出各组件的label前先读出legend里的内容。
举个小例子:
<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>
本例中,屏幕阅读器会将为第一个组件读出"Fruit juice size small",为第二个组件读出"Fruit juice size medium",为第三个组件读出"Fruit juice size large"。
上面这个例子是最重要的用法之一,当你有一堆单选按钮时,你得保证它们嵌套于<fieldset>
元素中。而通常来讲,<filedset>
元素也能用于给一个表单分段。
因为该元素对无障碍技术的影响,<fieldset>
元素已经成为构建无障碍表单的关键元素;但这也不是说你能够滥用它。当你构建表单时,能够试着听一下屏幕阅读器如何读取它,若听起来很奇怪,那就有必要改进你的表单结构了。
<fieldset>
元素支持如下的特有属性:
<fieldset>
元素的属性
属性名 | 默认值 | 描述 |
---|---|---|
disable | (false) | 若设置了该布尔值,表单中的后代元素(除了其第一个<legend> 元素的后代)将被禁用和禁止编辑。这些元素将再也不接收任何浏览器事件,譬如鼠标点击或和输入焦点有关的事件。一般浏览器会将这些元素显示为灰色。 |
<label>
元素用于给某个表单组件定义一个标签。若你想构建一个无障碍表单,这个元素可就是最重要的元素了。
<label>
元素支持如下的属性:
<label>
元素的属性
属性名 | 默认值 | 描述 |
---|---|---|
for | 值取在同一文档中可标记的组件的ID。 文档中第一个ID值匹配该属性值的元素就是被这个label元素标记的元素。 |
<label>
元素用for
属性绑定其对应的组件,for
属性可引用关联组件的id
值。此外组件也能够嵌套于其<label>
元素,但即便是这样,设置for
属性仍被认为是最佳作法,由于一些无障碍设备没法理解label和组件间的隐性关系(译注:其实嵌套就至关于自动设置了for
属性,不存在什么隐性关系,综合下文来看也这应该属于“最佳作法”的范畴吧)。
而即便不考虑无障碍技术,如有一个指派给特定组件的label,会让用户在点击label时,就能在全部浏览器下激活相应的组件。这就很是有便于使用单选按钮和复选框啦。
<form> <p> <input type="checkbox" id="taste_1" name="taste_cherry" value="1"> <label for="taste_1">I like cherry</label> </p> <p> <label for="taste_2"> <input type="checkbox" id="taste_2" name="taste_banana" value="1"> I like banana </label> </p> </form>
某些无障碍设备在处理指派多个label的单个组件时会出现问题。所以,你得把组件嵌套进相关联的元素,才能构建一个无障碍的表单(译注:不是很能理解这句话,上面不是说这种作法一些无障碍设备不能理解吗?并且解决方法不该该是不许多对一吗,和嵌套有半毛钱关系?)。
来看下面这个例子:
<form> <p>Required fields are followed by <strong><abbr title="required">*</abbr></strong>.</p> <!-- 当你要标记的组件是label的后代时,就不必在label上使用for属性了。 --> <!-- 因此这个: --> <label> <span>Name: </span> <input type="text" name="username" required /> <strong><abbr title="required">*</abbr></strong> </label> <!-- 和这个是同样的: --> <div> <label for="username">Name: </label> <input id="username" type="text" name="username" required /> <strong><abbr title="required">*</abbr></strong> </div> <p> <label for="birth"> <!-- 在这里,for属性就是多余的了。 --> <span>Date of birth: </span> <input type="text" id="birth" name="userbirth" maxlength="10" /> <em>formated as mm/dd/yyyy</em> </label> </p> </form>
在这个例子中,第一部分代码写的是必填元素的规则。该规则必须在表单头部以保证在用户找到必填元素以前,屏幕阅读器等无障碍设备能将其展现或读给用户。这样用户才能知道他到底该干吗。
第一个文本域是必填的,因此在其label元素内指明了该文本域的名字以及该文本域是必填的。如此一来,屏幕阅读器会把label读做"Name star"或"Name required"(这取决于屏幕阅读器的设定,一般与第一段写的那些规则相一致)。而若你使用了两个label,那就不能确保用户会被提示该元素是必填的。
第二个表单元素(译注:id
为birth
那个)也采用了一样的手段,使用上面例子的代码后,你就能保证用户在进入该字段时会被告知如何格式化日期数据了。
该元素用于存放计算的输出结果,它定义了用于获取运算数据的输入框和用于展现结果的元素间的联系。对于一些无障碍技术来说,该元素也能够认为是一个保持活动的区域(也就是说当<output>
元素的内容发生变化时,无障碍设备就能感知该变化并能对其作出响应)。
'<output>`元素支持如下的属性:
<output>
元素的属性
属性名 | 默认值 | 描述 |
---|---|---|
for | 一个用空格分隔的其余元素的ID列表,指示那些提供输入值(或其余效应)参与运算的元素 |
除了一些表单的具体结构,咱们还应知道表单其实就是HTML代码。这就意味着你能够用全部的HTML技术来构建一个表单。
就如你已经看到的例子中那样,一般咱们会把一个label及其对应的组件包裹在一个<p>
或<div>
元素中。
而除了<fieldset>
元素,咱们一般也会使用HTML的标题和section
来构建复杂的表单。
HTML的列表则经常使用在使用复选框和单选框时。
来看一个简单的支付表单例子:
<form> <h1>Payment form</h1> <p>Required fields are followed by <strong><abbr title="required">*</abbr></strong>.</p> <section> <h2>Contact information</h2> <fieldset> <legend>Title</legend> <ul> <li> <label for="title_1"> <input type="radio" id="title_1" name="title" value="M." /> Mister </label> </li> <li> <label for="title_2"> <input type="radio" id="title_2" name="title" value="Ms." /> Miss </label> </li> </ul> </fieldset> <p> <label for="name"> <span>Name: </span> <input type="text" id="name" name="username" required /> <strong><abbr title="required">*</abbr></strong> </label> </p> <p> <label for="mail"> <span>E-mail: </span> <input type="email" id="mail" name="usermail" required /> <strong><abbr title="required">*</abbr></strong> </label> </p> </section> <section> <h2>Payment information</h2> <p> <label for="card"> <span>Card type:</span> <select id="card" name="usercard"> <option value="visa">Visa</option> <option value="mc">Mastercard</option> <option value="amex">American Express</option> </select> </label> </p> <p> <label for="number"> <span>Card number:</span> <input type="text" id="number" name="cardnumber" required /> <strong><abbr title="required">*</abbr></strong> </label> </p> <p> <label for="date"> <span>Expiration date:</span> <input type="text" id="date" name="expiration" required /> <strong><abbr title="required">*</abbr></strong> <em>formated as mm/yy</em> </label> </p> </section> <section> <p> <button>Validate the payment</button> </p> </section> </form>
看一看执行效果吧(这里加了点CSS)
构建表单时,咱们须要一些组件来从用户那儿收集数据。因此在本文中,咱们还将看到如何呈现这些组件;若你想了解这些组件是如何工做的,可参见[原生表单组件]()。
这个元素至关特殊,由于它能够变成很多东西。只要简单设置下其type
属性,它就能发生大变化。为简单起见,type
的值可归为四种类型:单行文本框、无文本输入的控件、日期控件和按钮。而正因这种多样性,<input>
元素支持众多属性,但咱们很难知道其中那个是相关的、哪一个是必须的,这取决于type
属性的值。
下面的表格就是一个汇总(要得到完整的属性列表,请访问<input>
元素的页面):
若是咱们给type
属性设置的值不被浏览器支持,那它就会把<input>
元素渲染为和使用text
值同样的效果。这样能确保表单可使用,即便它看起来不那么吸引人。
虽然<input>
元素是个强大的工具,但它也并不是万能,因此还得一些其余元素来处理这些<input>
力不能及的状况。
该元素用于声明多行文本框。其行为与单行文本框基本一致,除了能让用户在输入文本时换行。此外该元素也接受几个额外的属性,以控制其在渲染时能占多大地方:
<textarea>
元素的属性
属性名 | 默认值 | 描述 |
---|---|---|
cols | 20 | 文本控件的可视宽度,单位是字符的平均宽度 |
rows | 文本控件的可视文本行数 | |
wrap | soft | 代表控件如何包含文本,可取值为hard 或soft |
注意<textarea>
元素的用法与<input>
元素稍有不一样。<input>
元素是个自闭合元素,这意味着它不能包含任何子元素。而另外一方面,<textarea>
元素则是个能够直接包含文本内容的普通元素。
这就形成两个影响:
若你想给<input>
元素定义默认值,你得使用valur
属性;而对于<textarea>
元素,你只需把默认文本置于其起始标签之间便可。
默认地,<textarea>
元素只接受文本内容;也就是说任何输入到<textarea>
元素内的HTML内容都会以纯文本的形式显示出来。
下面这个例子中,<textarea>
元素会以相同形式渲染出来:
<form> <p> <label for="text_1">With regular HTML</label><br> <textarea id="text_1" name="regular"><p>I'm a paragraphe</p></textarea> </p> <p> <label for="text_2">With escaped HTML</label><br> <textarea id="text_2" name="escaped"><p>I'm a paragraphe</p></textarea> </p> <p> <button>Send me</button> </p> </form>
<select>
元素能让你构建选择框(也叫组合框)。选择框是一种让用户选择一或多个预约义的值的组件。单值和多值选择框的不一样将在[原生表单组件]()一文中进行讨论。
选择框中的每一个值都会用一个<option>
元素进行定义,而这些<option>
元素也能够置于<optgroup>
元素中进行分组。
来看个例子:
<form> <p> <label for="myFruit">Pick a fruit</label> <select id="myFruit" name="fruit"> <!-- 这里耍了个小把戏,你觉得你选择了根香蕉,其实你是吃了个橘子 >:-) --> <option value="orange">Banana</option> <option>Cherry</option> <optgroup label="berries"> <option>Blueberry</option> <option>Raspberry</option> <option>Strawberry</option> </optgroup> </select> </p> </form>
若<option>
元素设置了value
属性,那么在表单提交时该值就会被提交。若value
属性未设置,则使用<option>
元素的内容做为整个选择框的值。
至于<optgroup>
元素,其label
属性将会先于其内容进行展现。并且它虽然看起来像一个选项,但实质上它是不可选的。
<option>
元素的属性
属性名 | 默认值 | 描述 |
---|---|---|
label | 该属性是用于描述选项的文本,若label 属性未被定义,那它的值就默认取元素的文本内容 |
|
selected | (false) | 目前来说,该布尔值代表选项是否在一开始就被选中 |
<optgroup>
元素的属性
属性名 | 默认值 | 描述 |
---|---|---|
label | 一组选项的名字。该属性是强制要有的 |
该元素经过为给定的组件预设值,实现了对已有组件的拓展,最广为人知的例子就是文本框的自动补全列表了。这些用于填充的值其实是经过<datalist>
元素里的<option>
元素进行设置的。
要把<datalist>
元素和某个组件绑定起来,你得先设置目标组件的list
属性;该属性需指定为相应的<datalist>
元素的id
属性。
<datalist>
元素是最近才被加入到HTML表单中的,故仍有些浏览器不支持它。这里有一个巧妙的兼容技巧,用于应对这些浏览器:
<form> <p> <label for="myFruit">What is your favorite fruit?</label> <input type="text" id="myFruit" name="fruit" list="fruitList" /> <datalist id="fruitList"> <label for="suggestion">or pick a fruit</label> <select id="suggestion" name="altFruit"> <option value="banana">Banana</option> <option value="cherry">Cherry</option> <option value="strawberry">Strawberry</option> </select> </datalist> </p> </form>
支持<datalist>
的浏览器将会忽略其中那些非<option>
元素,且最终效果和预期的同样。而支持<datalist>
的浏览器将会显示label和选择框。固然,也有别的方法来处理<datalist>
缺少支持的问题,但那得用到javascript,而这一般不是个好的选择。
这两个元素经常使用于图形化展现给定的数字值,二者的区别主要是语义上的:
<meter>
元素表明一个静态值,其相对位置在最大值和最小值之间。
progress
元素表明一个在最大值和最小值间随时间变化的值。值得注意的是,改变该元素的值(也就是显示进度)必须交给Javascript来完成,该元素自身没有任何机制来作到这一点。
默认的,这俩元素支持下列特有属性:
<meter>
元素的属性
属性名 | 默认值 | 描述 |
---|---|---|
min | 0 | 度量范围的数值下界 |
max | 1 | 度量范围的数值上界 |
low | min 值 |
比度量范围的下界要高的数值界限 |
high | max 值 |
比度量范围的上界要低的数值界限 |
optimum | 最佳数字值 |
译注:溢出low、high间的范围时,浏览器会以特殊样式显示<metter>
数值
<progress>
元素的属性
属性名 | 默认值 | 描述 |
---|---|---|
max | 该属性用于描述<progress> 对应的任务完成前须要作多少工做量 |
<button>
元素是最便于建立表单按钮的方式。一个按钮能够是三种类型质疑,由如下type
属性值决定:
submmit
按钮会把表单数据发送给由<form>
元素的action
属性定义的页面。
reset
按钮会当即把全部表单组件重置为默认值。从用户体验的角度看,如今认为使用这种按钮是一种糟糕的、应该避免的作法,由于它很容易让用户不当心就丢掉他们已填写的内容。
匿名(button
)按钮就没有固有属性了,你得使用Javascript来给其实现功能。
<button>
元素的属性
属性名 | 默认值 | 描述 |
---|---|---|
type | submit | 按钮的类型。可能的值有:button , reset , submit |
formaction | 若是按钮是个提交按钮,该属性的值会重写<form> 元素的action 属性 |
|
formentype | 若是按钮是个提交按钮,该属性的值会重写<form> 元素的enctype 属性 |
|
formmethod | 若是按钮是个提交按钮,该属性的值会重写<form> 元素的method 属性 |
|
formnovalidate | 若是按钮是个提交按钮,该属性的值会重写<form> 元素的novalidate 属性 |
|
formtarget | 若是按钮是个提交按钮,该属性的值会重写<form> 元素的target 属性 |
从技术上讲,用<button>
或<input>
元素定义的按钮间基本是没有区别的。只在按钮的标记上有一个值得注意的区别:在<input>
元素内标记只能是字符数据;而在<button>
元素内,标记的内容能够是HTML,因此此处按钮的样式能够被按需定制。
注意:由于一些历史缘由,
<button>
元素一直不被大量使用,且许多表单开发者更倾向于使用由<input>
构建的按钮。而罪魁祸首就是旧版本IE的一个bug,在IE6和IE7中,若你给<button>
元素加了name
和value
属性,表单就不会发送该value
属性而是直接发送按钮的内容。但这个bug已经在IE8以后给修复了,因此如今再也不有什么理由来回避使用<button>
元素了。
许多用来定义表单组件的元素拥有一些本身的属性,而这里还有一个全部表单元素的公共属性汇总,它们能给你跨组件的控制能力。下面就是这些公共属性的列表:
属性名 | 默认值 | 描述 |
---|---|---|
autofocus | (false) | 这个布尔属性让你可以指定在页面加载时须要自动得到输入焦点的元素,除非用户重写了它,好比在另外一控件上输入。在一个文档中,只能有惟一一个表单元素能指定该值。 |
disabled | (false) | 这个布尔属性代表用户不能与某个元素交互。如该属性未指定,则会继承自容器元素如<fieldset> 的设置;若无容器元素设置了disabled 属性,则该元素就是可用的 |
form | 和组件关联的form元素。这个属性的值必须是同一文档下某<form> 元素的id 值。理论上,这能让你在<form> 元素外设置表单组件。但在实际应用中,并无浏览器支持该特性。 |
|
name | 元素的名字,该属性会随表单数据提交 | |
value | 指定元素初始值 |
ARIA是一项W3C候选推荐标准,用于添加到HTML以加强富Internet应用的可访问性。咱们将在[怎样建立定制表单组件]()一文中更具体地讨论它的使用,但这里有一些基础知识须要先知道。
在开始以前,要注意浏览器上对ARIA和无障碍技术的支持虽然还远称不上完美,但也已在持续改进之中了。出现这种问题就是由于,浏览器在遇到ARIA属性时,必须给操做系统的无障碍访问层发送消息,而并非全部浏览器都能跨平台地作好这点。同时无障碍设备自身只能连接到操做系统的无障碍访问层去处理浏览器传来的消息。让人吃惊的是,有些无障碍设备连这点都作很差。
因此使用无障碍技术并不意味着你的web应用就是无障碍的,而是意味着你已经尽力来作到这点了。暂时来说,ARIA只是尽最大努力的技术,但仍是聊胜于无吧。
若你还想深刻了解ARIA和HTML表单的结合使用,请自行阅读ARIA文档的相关章节。
该属性便于在不适用<label>
元素时定义一个label。可将其放在组件元素上并引用要做为label的元素的id
属性。
<form> <p id="fruitLabel">What's your favorite fruit</p> <p> <input type="text" name="fruit" aria-labelledby="fruitLabel"> </p> </form>
从概念上,这个属性与<label>
元素的for
属性正好相反。使用for
属性时引用的是组件的id
,而使用aria-labelledby
时则引用label的id
。
该属性和aria-labelledby
做用相似,主要就是语义上有不一样。label用于定义对象的本质内容,而描述则提供更多用户可能要用到的信息。这个属性不建议直接用在表单元素上;最好仍是使用aria-labelledby
属性,除非你想为当前元素提供额外信息。毕竟该属性就是用来提供大段描述的。
该属性用于给定的组件在DOM中没有明确的label时,它能让你提供一个能经过无障碍设备使用的组件,而无需专门为其建立一个节点来作到这点。
<form> <p> <input type="search" name="q" aria-label="Search" /> <input type="submit" value="Go" /> </p> </form>
这是最重要的一个ARIA属性了,它能让你为给定的HTML元素提供无障碍设备可理解的、特定的语义信息。如今已经有很多可用的role了,且其中一些是表单专用的。
ARIA致力于给那些在HTML中尚不可用的组件、或已经存在的元素提供语法,咱们将会在[怎样建立定制表单组件]()一文中看到如何使用这些role。
用于表单组件的role有:
Radio
Spinbutton
值得注意的还有几个复合的role:
Radiogroup
若你以为这些role很好用,可在这里了解更多;ARIA是个很庞大的规范,深刻探索它能帮你为远超HTML表单以外的领域加强无障碍性。
如今你已经拥有了全部可用于构建你的HTML表单的知识;下篇文章将会深刻其实现细节和功能需求:[原生表单组件]()。