label 關聯:最基本、最常被跳過的
<!-- ❌ placeholder 代替 label:使用者輸入後看不到提示 -->
<input type="text" placeholder="姓名">
<!-- ✅ 方法一:for + id 關聯 -->
<label for="name">姓名</label>
<input type="text" id="name" name="name">
<!-- ✅ 方法二:label 包起來(不需要 id) -->
<label>
姓名
<input type="text" name="name">
</label>label 的作用不只是視覺文字——點擊 label 文字會聚焦到對應的 input,螢幕閱讀器會朗讀 label 內容。沒有 label 只有 placeholder,使用者輸入後就失去提示,螢幕閱讀器使用者完全不知道這個欄位是什麼。
錯誤訊息的出現時機
最常見的錯誤:使用者按送出才一次顯示所有錯誤。使用者要往回捲、一個個修、再送出,挫折感很高。
三種時機的取捨:
| 時機 | 觸發條件 | 適用場景 |
|---|---|---|
| on blur | 欄位失焦時驗證 | 大多數欄位的預設選擇 |
| on change | 輸入中即時驗證 | 密碼強度、即時搜尋 |
| on submit | 按送出才驗證 | 只在前兩個都沒辦法用時 |
<!-- 錯誤訊息要放在欄位附近,用 aria-describedby 關聯 -->
<div>
<label for="email">Email</label>
<input
type="email"
id="email"
name="email"
aria-describedby="email-error"
aria-invalid="true"
>
<span id="email-error" role="alert">請輸入有效的 Email 格式</span>
</div>aria-invalid="true" 讓螢幕閱讀器知道這個欄位有錯;role="alert" 讓錯誤訊息出現時立即朗讀。
錯誤訊息的文字原則:
- ❌「格式錯誤」(說了等於沒說)
- ❌「Invalid input」(沒說哪裡錯)
- ✅「請輸入 email 格式,例如 name@example.com」(說清楚正確格式)
Tab order:鍵盤使用者的移動路線
Tab 鍵在欄位間跳轉的順序預設跟 DOM 順序一致。不要用 tabindex 強制改順序——這幾乎總是代表 HTML 結構需要調整。
<!-- ❌ 用正數 tabindex 強制排序,會打亂螢幕閱讀器和鍵盤使用者 -->
<input tabindex="3" name="last-name">
<input tabindex="1" name="first-name">
<input tabindex="2" name="email">
<!-- ✅ 讓 DOM 順序就是正確順序 -->
<input name="first-name">
<input name="last-name">
<input name="email">tabindex="0" 是讓原本不可聚焦的元素(<div>、<span>)加入 tab 順序,有時候必要。tabindex="-1" 是讓元素可以用 JS 的 .focus() 聚焦但不在 tab 順序裡(modal 開啟時自動聚焦用)。
行動裝置鍵盤優化
除了前一篇說的 type 屬性,還有幾個屬性影響行動裝置體驗:
<!-- inputmode:不換 type 但改鍵盤 -->
<!-- 身分證號是文字但要數字鍵盤 -->
<input type="text" name="id-number" inputmode="numeric" pattern="[0-9]*">
<!-- 小數點數字 -->
<input type="text" name="price" inputmode="decimal">
<!-- 搜尋(鍵盤右下角顯示搜尋鍵) -->
<input type="search" inputmode="search">
<!-- enterkeyhint:enter 鍵顯示什麼文字 -->
<input type="text" enterkeyhint="next"> <!-- 下一步 -->
<input type="text" enterkeyhint="done"> <!-- 完成 -->
<input type="text" enterkeyhint="search"> <!-- 搜尋 -->
<input type="text" enterkeyhint="go"> <!-- 前往 -->inputmode 比 type 更細緻——你可以保留 type="text"(不觸發瀏覽器格式驗證),但用 inputmode="numeric" 讓行動裝置彈出數字鍵盤。
必填欄位的正確標示
<!-- ✅ HTML required + 視覺標示 + aria -->
<label for="email">
Email
<span aria-hidden="true">*</span>
<span class="sr-only">(必填)</span>
</label>
<input type="email" id="email" name="email" required aria-required="true">
<!-- 表單頂端說明星號意思 -->
<p><span aria-hidden="true">*</span> 標示為必填欄位</p>aria-hidden="true" 讓螢幕閱讀器忽略視覺上的 *,改讀旁邊的「(必填)」文字,避免使用者聽到「Email 星號」這種奇怪的朗讀。
相關文章
- 表單原生行為 — form 提交、constraint validation API
- 表單進階 — input types、autocomplete、file upload
- ARIA 和原生語意 — aria-describedby / aria-invalid 的使用時機