大多數網站和應用程式都包含網路表單。跟笑話網站 (如 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 方法,以及處理表單提交作業的網址。是的,您可以提交表單、處理表單,並在不使用任何 JavaScript 的情況下載入新頁面。<form>
元素就是這麼強大。
<form>
元素的 action
和 method
屬性值分別定義處理表單資料的網址,以及用於提交資料的 HTTP 方法。根據預設,表單資料會傳送至目前的網頁。否則,請將 action
屬性設為資料應傳送至的網址。
傳送的資料是由表單各種表單控制項的名稱/值配對組成。根據預設,這會包含所有巢狀結構形式的表單控制項,且該表單中含有 name
。不過,您可以使用 form
屬性,在 <form>
外部納入表單控制項,並省略在 <form>
內嵌的表單控制項。支援表單控制項和 <fieldset>
,form
屬性的值為與控制項相關聯的表單的 id
,不一定是嵌套在其中的表單。也就是說,表單控制項不必實際巢狀結構在 <form>
中。
method
屬性會定義要求的 HTTP 通訊協定:通常為 GET
或 POST
。使用 GET
時,表單資料會以 name=value
組合的參數字串傳送,並附加至 action
的網址。
使用 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」(或不採取任何動作,因為瀏覽器會顯示並預設選取第一個選項值),然後按一下提交按鈕,系統就會重新載入這個頁面,並將網址設為:
https://web.dev/learn/html/forms?student=hoover
由於第二個選項沒有 value
屬性,因此內文會以值的形式提交。選取「Blendan Smooth」並點選提交按鈕後,系統會重新載入這個頁面,並將網址設為:
https://web.dev/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://web.dev/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>
會位於表單控制項之前,但圓形按鈕和核取方塊除外。這不是必要步驟。
這是常見的使用者體驗模式。「瞭解表單」系列文章提供表單設計相關資訊。
對於圓形按鈕和核取方塊群組,標籤會為相關聯的表單控制項提供無障礙名稱;但控制項群組和其標籤也需要標籤。如要為群組加上標籤,請將所有元素歸入 <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 -->
這些元素的預設外觀導致使用率偏低,但您可以使用 CSS 為 <legend>
和 <fieldset>
設定樣式。除了所有全域屬性外,<fieldset>
也支援 name
、disabled
和 form
屬性。當您停用欄位集時,系統會停用所有巢狀表單控制項。name
和 form
屬性在 <fieldset>
上用途不大。name
可用於透過 JavaScript 存取欄位集,但欄位集本身不會包含在提交的資料中 (包含巢狀結構中的已命名表單控制項)。
輸入類型和動態鍵盤
如前所述,有 22 種不同類型的輸入內容。在某些情況下,如果使用者的裝置配有動態鍵盤,而該裝置只會在需要時顯示 (例如手機),使用的輸入類型會決定顯示的鍵盤類型。系統會根據所需的輸入類型,為顯示的預設鍵盤進行最佳化。舉例來說,輸入 tel
會顯示專為輸入電話號碼而最佳化的按鍵盤;email
包含 @
和 .
;而 url
的動態鍵盤則包含冒號和斜線符號。很抱歉,iPhone 仍未在 url
輸入類型的預設動態鍵盤中加入 :
。
<input type="tel">
適用於 iPhone 和兩個不同 Android 手機的鍵盤:
<input type="email">
適用於 iPhone 和兩部不同 Android 手機的鍵盤:
存取麥克風和相機
<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
已設定或未設定)、checked
是否已硬式編碼,以及 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 程式碼片段是反模式。雖然您的使用者介面可能會讓使用者覺得直覺且清楚,但許多使用者會嘗試提交表單,以便顯示錯誤訊息。以這種方式讓提交按鈕顯示為已停用,會導致許多使用者仰賴的限制條件驗證功能無法運作。
套用的 CSS 會根據 UI 目前的狀態持續更新。舉例來說,如果您納入含有限制條件的輸入類型,例如 email
、number
、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 的內部網路電子郵件地址視為有效地址。您可以使用 pattern 屬性提供值必須相符的規則運算式。要求使用者輸入模式比對時,請務必讓使用者清楚瞭解預期結果。
無須編寫一行 JavaScript 即可完成上述操作,但如果是 HTML API,您可以在限制驗證期間,使用 JavaScript 加入自訂訊息。您也可以使用 JavaScript 更新剩餘字元數量、顯示密碼強度進度條,或透過其他方式動態改善完成度。
範例
這個範例的 <dialog>
中有一份表單,內含巢狀 <form>
,其中包含三個表單控制項和兩個提交按鈕,並包含清楚的標籤和操作說明。
第一個提交按鈕會關閉對話方塊。使用 formmethod="dialog"
覆寫表單的預設方法,關閉 <dialog>
,而不提交資料或清除資料。您也必須加入 formnovalidate
,否則瀏覽器會嘗試驗證所有必要欄位是否都有值。使用者可能會想在不輸入任何資料的情況下關閉對話方塊和表單,驗證機制可防止這種情況發生。請加入 aria-label="close"
,因為「X」是已知的視覺提示,但並非描述性標籤。
表單控制項都含有隱含標籤,因此您不需要加入 id
或 for
屬性。兩個輸入元素都具有必要屬性,因此為必要元素。數字輸入內容已明確設定 step
,以示範如何納入 step
。由於 step
預設為 1
,因此可以省略這個屬性。
<select>
有預設值,因此不需要使用 required
屬性。系統不會在每個選項中加入 value
屬性,而是將值預設為內部文字。
結尾處的提交按鈕會將表單方法設為 POST。點選後,系統會檢查每個值的有效性。如果所有值皆有效,系統就會提交表單資料、關閉對話方塊,且網頁可能會重新導向至 thankyou.php
(即動作網址)。如果缺少任何值,或數值步驟不相符或超出範圍,系統會顯示相關瀏覽器定義的錯誤訊息,且不會提交表單,對話方塊也不會關閉。您可以使用 validityState.setCustomValidity('message here')
方法自訂預設錯誤訊息。請注意,如果您設定了自訂訊息,則訊息必須明確設為空字串 (當一切有效),否則表單將無法提交。
其他注意事項
讓您全面瞭解如何協助使用者在表單中輸入正確資料。為了提供良好的使用者體驗,請務必在必要時加入操作說明和提示,避免使用者犯錯。雖然本節說明如何單獨使用 HTML 提供用戶端驗證,但驗證必須同時在用戶端和伺服器端進行。在填寫表單時,您可以以不顯眼的方式提供驗證,例如在值正確時加入勾號。不過,請勿在表單控制項完成前提供錯誤訊息。如果使用者確實犯錯,請告知使用者錯誤所在,以及他們做錯了什麼。
設計表單時,請務必記住,名稱、地址格式等全球各有不同的標準。某人可能會使用單一字母做為姓氏 (或根本沒有姓氏)、沒有郵遞區號、使用三行街道地址,或沒有街道地址。這位使用者可能正在查看表單的翻譯版本。
表單控制項、標籤和錯誤訊息應顯示在畫面上,且應透過程式輔助方式確定正確且有意義的,並以程式輔助方式與適當的表單元素或群組建立關聯。autocomplete
屬性可用於加快表單填寫速度,並改善無障礙功能,而且應予以使用。
HTML 提供所有工具,可讓基本表單控制項更容易存取。表單元素或程序的互動性越高,就越需要重視相關的無障礙功能,包括焦點管理、設定及更新 ARIA 名稱、角色和值 (視需要),以及 ARIA 即時公告。不過,如同我們在本篇文章中所學到的,只要使用 HTML,您就能大幅達成無障礙和有效性目標,而無須使用 ARIA 或 JavaScript。
進行隨堂測驗
測驗您對表單的瞭解程度。
如何讓圓形按鈕屬於同一個群組?
name
屬性值。id
屬性值。哪一個 HTML 元素可用來向使用者說明這個表單欄位的功用?
<label>
<h1>
<title>