大多數的網站和應用程式都包含網路表單。笑話網站 (例如 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
。限制驗證會在提交表單前進行,但前提是已啟用的提交按鈕及 <form>
上沒有 formnovalidate
,也沒有 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」(或不執行任何動作,因為瀏覽器會顯示,因此預設選取第一個選項值),然後按一下「Submit」按鈕,即可重新載入這個頁面,並將網址設為:
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
輸入類型的預設動態鍵盤中加入 :
。
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
),與表單控制項相符;如果已設定布林值 required
,則:default
如果 checked
是硬式編碼;而 :enabled
或 :disabled
則取決於元素是否為 :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
和日期類型等限制的輸入類型,且值是非空值 (非空白) 且目前值不是有效的電子郵件地址、數字、網址、日期或時間,: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
還是預設為 1
,控制項就是 :out-of-range
(和 :invalid
),且會發生 validityState.stepMismatch
錯誤。根據預設,錯誤訊息會以對話框形式顯示,並提供解決問題的實用資訊。
值長度也有類似的屬性:minlength
和 maxlength
屬性會在提交時提醒使用者有 validityState.tooLong
或 validityState.tooShort
發生錯誤。maxlength
也會禁止使用者輸入過多字元。
使用 maxlength
屬性可能導致使用者體驗不佳。一般而言,讓使用者能輸入超過系統規定的字元長度上限,並可選擇採用 <output>
元素的形式 (未透過表單提交),讓使用者可以向下編輯文字,直到輸出顯示超過允許的長度上限為止。您可以在 HTML 中加入 maxlength
;如同我們先前討論的任何內容,在沒有 JavaScript 的情況下也能運作。然後,載入時可以使用 maxlength 屬性的值,在 JavaScript 中建立這個字元計數器。
部分輸入類型似乎有預設限制條件,但不會有預設限制。舉例來說,tel
輸入類型在具有動態鍵盤的裝置上提供數字電話鍵盤,但不會限制有效值。而其他輸入類型則是 pattern
屬性。您可以指定值符合的有效規則運算式。
如果值為空字串,且此值非必要,則不會造成 validityState.patternMismatch
錯誤。如果必要且空白,使用者會看到 validityState.valueMissing
的預設錯誤訊息,而非 patternMismatch
。
如果是電子郵件,validityState.typeMismatch
可能不足以滿足您的需求。建議您加入 pattern
屬性,讓系統將沒有 TLD 的內部網路電子郵件地址視為有效。模式屬性可讓您提供值必須相符的規則運算式。要求比對模式時,請確保使用者能清楚瞭解預期的回應。
無需單行 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 即時公告和 ARIA 即時公告方面,必須獲得更多注意力,以無障礙的方式管理。不過,正如我們在這裡所學,如果只使用 HTML,不必改用 ARIA 或 JavaScript,就能大幅提高無障礙和有效性。
隨堂測驗
測驗您對表單的相關知識。
如何讓圓形按鈕屬於同一個群組?
name
屬性值。id
屬性值。哪一個 HTML 元素的用途是讓使用者知道這個表單欄位的用途?
<h1>
<title>
<label>