在創建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表單的知識;下篇文章將會深刻其實現細節和功能需求:[原生表單組件]()。