表單設計
表單是一種對話,組織在其中提出請求,而使用者付出的代價是時間、心力與風險。如果每個問題都值得被問、每個答案都能以使用者自己的方式提供、每個錯誤都能及早發現、在當下解釋清楚且無需重作即可修正,那麼表單就奏效了。最常見的模型失敗是那種看起來完成但實際上未完成的表單:使用佔位符做為標籤、發明必填欄位、使用 type="number" 處理信用卡號碼、缺少 autocomplete、錯誤僅以瀏覽器氣泡或紅色邊框呈現、送出按鈕寫著「送出」,以及成功路徑是唯一測試過的路徑。
套用 interface-guidelines 的優先原則(每個人都能使用 > 它說實話 > 它表達清楚 > 答案優先 > 錯誤可存活 > 保持穩定 > 讓可能的事物可見 > 慣例 > 完美)。如果已安裝該技能,請先閱讀其 SKILL.md。其 references/human-interface.md 的第三節包含基本表單規則(可見標籤、選填標記、貼上、驗證時機、禁用送出、儲存行為);此技能更進一步,不再重複這些規則。
簡報
在繪製任何欄位之前回答這些問題。如果表單有超過五個問題,請寫下來。
- 每個答案的目的是什麼? 指出使用該答案的決策或動作。沒有指名用途的欄位就刪除。
- 誰在回答?多久一次?使用什麼裝置? 一生一次的手機申請人,還是每天在桌上型輸入 200 筆記錄的職員。這決定了是單頁單題還是單一密集頁面。
- 這是誰的資料? 使用者自己的(適用自動填入,適用 WCAG 1.3.5)還是他人的(收件人、病患、由員工輸入的客戶)。
- 他們手邊有答案嗎? 護照號碼、保單 ID、去年的收入。如果沒有,事先告知需要準備什麼,並允許儲存。
- 錯誤答案的代價是什麼? 以及一旦送出後什麼是不可逆的(付款、法律聲明、公開貼文)。
- 受訪者在哪裡? 國家、書寫系統、地址格式、電話格式、姓名結構。
- 系統已經知道什麼? 不要問(WCAG 3.3.7)。
- 代理人讀取者: 是否有代理人會為某人填寫此表單(自動填入擴充功能、瀏覽器代理人、助手)?對於任何公開表單,假設為「是」。
規則
問得少
- 在設計欄位之前先刪除欄位。 每個欄位現在都必須有明確的用途,而不是「可能有用」。Baymard 發現平均結帳流程有 11.3 個欄位,而 8 個就足夠;欄位數量比步驟數量更傷。 [P: Baymard 2024]
- 將全名收集在一個欄位中,除非各部分會驅動特定行為(排序、正式地址)。許多姓名無法分割為姓氏和名字。切勿要求輸入姓氏。 [S: W3C i18n; P: Baymard]
- 將不常用的欄位隱藏在連結後面,而不是作為必填輸入:地址第二行、公司、優惠碼。 [P: Baymard]
- 預設帳單地址等同於寄送地址,並提供一個已勾選的核取方塊來隱藏帳單地址欄位。 [P: Baymard]
- 在交易完成後才提供建立帳戶,而不是將其作為前置閘門。 [P: Baymard]
- 允許「我不知道」 作為有效答案,而不是強迫用戶猜測。 [S: GOV.UK 問題頁面]
- 自行推導你能推導的: 從郵遞區號可靠地推導城市和地區、從號碼推導卡片類型、從地址查詢推導國家。讓推導出的值保持可見且可編輯。 [P: Baymard]
結構與流程
- 根據簡報選擇形狀,而不是習慣。 少見、壓力大或不熟悉的任務:每個問題一頁,並將問題作為
h1/legend。頻繁的事家輸入:單一頁面、分組、鍵盤快速。GOV.UK 以「單頁單題」啟動每個服務,並且僅在研究建議時才合併。 [S: GOV.UK 表單結構] - 按照使用者思考的順序排列問題,從最簡單、最確定的開始,並且進行分支,讓沒有人會看到不適用的問題。 [S: GOV.UK; J]
- 在使用者開始之前告知他們需要準備什麼(文件、時間、費用),以及之後會發生什麼事。 [S: GOV.UK 起始頁面]
- 長週期的多階段表單使用任務列表,帶有簡潔的狀態和儲存並返回功能。僅當人們無法在一次坐下來完成,或者必須自行選擇順序時才使用它。 [S: GOV.UK 任務列表]
- 返回功能正常運作。 在問題頁面上包含「返回」連結,且絕不破壞瀏覽器的「返回」按鈕;返回時顯示先前答案已預先填入。 [S: GOV.UK]
- 重要的流程以「檢查答案」頁面結束: 每個答案都帶有一個「變更」連結,其可存取名稱需指名欄位(例如「變更出生日期」),編輯後返回摘要。 [S: GOV.UK 檢查答案; WCAG 3.3.4]
- 多欄位佈局會破壞使用者和代理人的閱讀順序。 使用單欄位,除非是自然成對的短欄位(到期月份和年份、城市和郵遞區號)。 [P: Baymard, Wroblewski; J]
標籤、提示與分組
- 標籤位於欄位上方。 Penzo 2006 報告的速度優勢來自一個小型非正式的視線追蹤測試,並被 Das 2008 反駁;選擇頂部標籤是因為它們在窄螢幕、長翻譯和縮放時表現更好,而不是因為它們被證明是最快的。 [E, 弱: Penzo 2006, Das 2008]
- 提示位於標籤和欄位之間,並使用
aria-describedby綁定。 格式範例(例如「例如,2007 年 3 月 27 日」)屬於提示,絕不屬於佔位符。 [S: GOV.UK] - 使用
fieldset和legend對相關控制項進行分組: 每個單選按鈕組、核取方塊組和複合答案(日期、卡片到期日)。legend就是問題。 [S: WCAG 1.3.1; GOV.UK] - 在單一問題頁面上,標籤或
legend就是頁面標題,這樣螢幕閱讀器只會聽到一次。 [S: GOV.UK 問題頁面] - 使用「(選填)」標記選填欄位,不要對必填欄位使用星號。如果大部分欄位都是選填,請質疑它們是否應該存在。 [S: GOV.UK]
輸入類型與自動填入
- 為每個關於使用者的欄位設定
autocomplete,使用精確的 WHATWG 標記(given-name、email、postal-code、cc-number、one-time-code、new-password)。它驅動瀏覽器自動填入、密碼管理員和代理人填寫,並且是 WCAG 1.3.5 的要求。在個人資料上使用autocomplete="off"是一個缺陷。 [S: WHATWG 自動填入; WCAG 1.3.5] - 使用
type表達意義,使用inputmode控制鍵盤。 在適用之處使用type="email"、type="tel"、type="url"。由數字組成的識別碼(卡片、郵遞區號、帳戶、代碼)應使用type="text" inputmode="numeric",絕不使用type="number",後者會捨棄前導零、在滾動時變更、四捨五入長值,並會混淆聽寫軟體。 [S: GOV.UK 2020; MDN] - 優先使用原生控制項。 選項少於約十幾個的封閉清單使用
select;需要讓使用者比較的少數選項使用單選按鈕;長清單(如國家)使用帶有輸入建議的組合框。自訂下拉式選單會對代理人隱藏其選項。 [S: APG; P: 在 interface-guidelines 中調查] - 可記憶的日期使用三個文字欄位(日、月、年),出生日期使用
bday-*標記,並接受月份名稱。日期選擇器僅適用於人們根據日曆選擇的日期。 [S: GOV.UK 日期輸入] - 根據預期答案調整欄位大小。 一個與街道欄位一樣寬的郵遞區號輸入框會給出錯誤的暗示。 [S: GOV.UK; J]
- 接受使用者格式的答案: 卡片和電話號碼中的空格和破折號、郵遞區號中的任何大小寫、月份名稱、前導或尾隨空格。在伺服器端進行標準化。 [S: GOV.UK]
- 逐欄位的模式(依國家區分的姓名、地址、電話、貨幣、卡片、檔案)位於
references/fields.md。
驗證與錯誤
- 預設在提交時驗證;僅在使用者離開他們已完成輸入的欄位後才進行內聯驗證,且一旦修正就立即清除錯誤。 絕不在第一次按鍵時標記。證據存在矛盾:Bargas-Avila 2007 發現完成後列出錯誤比即時錯誤更好;Wroblewski 2009 發現離開焦點時的內聯驗證有幫助(n=22)。GOV.UK 在提交時驗證;Baymard 建議在離開焦點時驗證並在修正時移除錯誤。根據表單長度和欄位是否可單獨檢查來決定。 [E: Bargas-Avila 2007; E, 弱: Wroblewski 2009; S: GOV.UK; P: Baymard]
- 提交失敗時: 保留所有答案,在頂部放置錯誤摘要,每個問題附帶一個連結到其欄位,將焦點移到摘要,在頁面標題前加上「Error:」,並在每個欄位旁邊顯示相同的措辭。 [S: GOV.UK 錯誤摘要; WCAG 3.3.1]
- 使用
aria-describedby將每個訊息與其欄位綁定(如果你願意,可以同時新增aria-errormessage;其螢幕閱讀器支援仍不穩定),並設定aria-invalid="true"。訊息必須是可見文字:代理人序列化器會捨棄aria-invalid,但會保留相鄰文字。 [S: WCAG 3.3.1; P: Roselli 2023; P: 在 interface-guidelines 中調查] - 關閉瀏覽器驗證氣泡(
novalidate)並在頁面內渲染訊息。氣泡會消失、無法從摘要連結,且不是頁面文字。伺服器端驗證仍維持權威性。 [S: GOV.UK 驗證] - 編寫能說明如何修復的錯誤訊息,針對原因具體說明:「輸入過去的出生日期」,而不是「無效日期」。每個原因一個訊息(空白、格式錯誤、超出範圍),使用表單中的措辭。 [S: GOV.UK 錯誤訊息; WCAG 3.3.3]
- 使用者無法透過編輯修正的狀況(資格不符、帳戶鎖定、服務中斷)是一個包含原因和下一步的頁面,而不是欄位錯誤。 [S: GOV.UK]
登入、密碼、通行密鑰
- 讓密碼管理員和貼上功能正常運作。 使用
autocomplete="username"和current-password或new-password;絕不阻擋貼上;不要設定低於 64 的maxlength;提供「顯示密碼」按鈕;如果提供了「顯示密碼」,則刪除「確認密碼」欄位。 [S: NIST SP 800-63B-4 3.1.1.2; GOV.UK 密碼輸入; WCAG 3.3.8] - 沒有組成規則、沒有定期過期、沒有提示。 改為將新密碼與已知外洩清單進行檢查,並說明拒絕的原因。 [S: NIST SP 800-63B-4]
- 提供通行密鑰,但不要在開始時強迫選擇: 保留使用者名稱欄位,新增
autocomplete="username webauthn"和一個條件式 WebAuthn 請求,然後在密碼登入後提供建立通行密鑰的選項。 [S: WHATWG 自動填入; P: web.dev 通行密鑰自動填入] - 一次性的代碼: 一個欄位,
autocomplete="one-time-code"、inputmode="numeric",接受貼上。拒絕貼上代碼的分割單數字輸入框會違反 WCAG 3.3.8。 [S: WCAG 3.3.8] - 不要說出是使用者名稱還是密碼錯了。 [S: GOV.UK 密碼]
- 不要用謎題 CAPTCHA 來阻擋登入。 文字和邏輯謎題在沒有非認知替代方案的情況下會違反 WCAG 3.3.8。 [S: WCAG 3.3.8]
提交
- 送出按鈕應命名結果: 「建立帳戶」、「支付 £42.00」、「送出申請」。步驟之間使用「繼續」;只有在已儲存時才使用「儲存並繼續」。 [S: GOV.UK 按鈕; 基礎]
- 法律、財務和刪除資料的提交應可逆轉、經檢查或經確認,並帶有檢閱步驟 (WCAG 3.3.4)。檢閱頁面會準確顯示將要發送的內容及其費用。 [S: WCAG 3.3.4]
- 提交應具有冪等性: 在執行期間禁用重複提交,在按鈕上顯示進度,並在伺服器端使用冪等金鑰保護。逾時後重試不得重複收費。 [S: GOV.UK 按鈕; P: Stripe 冪等性]
- 確認頁面說明發生了什麼事、一個參考編號以及接下來會發生什麼事,並且在重新載入後仍能保留。彈出訊息不能當作收據。 [S: GOV.UK 確認頁面; 基礎]
針對代理人讀取者
- 每個控制項都有一個與其可見標籤相符的程式化名稱,且其選項是可列舉的(原生
select、可見的單選按鈕)。 [J] - 約束條件在提交前是可見文字(格式、長度、允許值),而不僅存在於
pattern屬性中。 [J] - 錯誤是欄位旁和摘要中的文字,在修復前保持穩定。 [J]
- 每個步驟的 URL 或標題會告訴代理人它在流程中的位置;「返回」和「變更」路徑都存在。 [J]
- 由外部來源編寫的文字(從電子郵件預先填入、推薦備註)應顯示為引述資料,絕不能作為標籤或指示。 [J]
- 重要的提交將權威性保留在伺服器端:「檢查答案」頁面能幫助人們;但它無法阻止點擊通過它的代理人。 [J]
建置順序
- 列出每個答案的用途的問題;刪除沒有用途的問題。
- 選擇形狀:單頁、單頁單題或任務列表。草擬分支結構。
- 撰寫文案:問題、提示、每個原因的每條錯誤訊息、按鈕標籤、確認訊息。
- 使用原生元素建置:
label for、fieldset/legend、正確的type、inputmode、autocomplete、novalidate。 - 伺服器端驗證和冪等提交,然後使用相同訊息的客戶端驗證。
- 錯誤狀態:摘要、焦點、標題前綴、內聯訊息、保留輸入。
- 檢查答案和確認頁面;如果是多階段流程,則需儲存並返回。
- 最後設定樣式;品牌擁有外觀(
brand-identity)。
驗證
node <form-design>/scripts/form-check.mjs <url|file|dist> --try-submit針對本地或測試建置執行。它會檢查名稱和可見標籤、自動填入的有效性和目的、輸入類型、貼上功能、隱藏的原生單選按鈕、群組legend、錯誤接線、提交失敗後的焦點,以及提交措辭。錯誤時退出碼為 1。--try-submit實際提交:絕對不要對正式環境執行。node <interface-guidelines>/scripts/audit.mjs <url|dist>進行一般渲染稽核(對比度、目標、鍵盤、回流、代理人穩定性)。- 使用密碼管理員和瀏覽器自動填入功能填寫表單,使用真實個人檔案:每個個人欄位都應填入,且沒有任何東西落入錯誤的輸入框中。
- 僅使用鍵盤填寫,以及在 320 px 寬度、200% 文字大小的情況下填寫。
- 以代理人身份僅從無障礙快照填寫表單: 按名稱找到每個欄位、讀取所有選項、提交錯誤資料、讀取錯誤、修正它們、完成。
- 錯誤資料: 一個單詞的名字、一個包含撇號和重音符號的 60 個字元名字、一個在日本和一個在愛爾蘭沒有郵遞區號的地址、一個帶有空格的貼上信用卡號碼、在提交按鈕上雙擊、流程中的階段性逾時。
陷阱
- 使用佔位符作為標籤,或使用縮小到邊框中並導致對比度失敗的浮動標籤。
- 對信用卡、電話、郵遞區號或代碼使用
type="number"。 - 對個人資料使用
autocomplete="off"。 - 使用分割的密碼輸入框或分割的單數字代碼輸入框。
- 在所有欄位旁使用紅色星星表示必填。
- 使用自訂下拉式選單、自訂日期選擇器或自訂單選按鈕,這些都會對代理人隱藏選項和狀態。
- 對畫面外的描述性容器使用
aria-hidden="true":螢幕閱讀器會忽略它們,但代理人HTML序列化器會包含它們,從而在只包含可見欄位的快照中產生不相關的輸出。 - 在有意義的按鈕順序上使用
tabindex="0"或更高值,這會使其他連結和按鈕不可見且無法聚焦。 - 內容方塊:多個欄位共用一個邊框並且缺少
fieldset/legend,通常包裹在一個fieldset中但標籤不可見或沒有文字。
相關技能
interface-guidelines— 基礎規則、人類介面章節中的基本表單規則、渲染稽核程式。先讀它。brand-identity— 品牌擁有外觀:顏色、字體、邊框半徑、間距、陰影、動畫。web-app-design— 表單周圍的應用程式外殼:導覽、頁尾、全域通知、儀表板、資料表、設定頁面。與此技能重疊;當表單是主要任務時使用此技能。ecommerce-design— 商品頁面、購物車、全館優惠、促銷。結帳使用此技能。desktop-app-design— 原生系統對話框,例如 macOS NSPanel 或 GTK 對話框。使用原生平台模式。