
前言
本指南將詳盡介紹所有 HTML5 原生的表單驗證屬性,包括 required、pattern、min、max、step、type、maxlength、minlength、multiple、readonly、disabled、novalidate、formnovalidate 等,並說明如何將它們應用在 <input>、<textarea>、<select> 等表單元素上。我們也會探討如何透過 JavaScript 自訂驗證邏輯(使用 setCustomValidity()、checkValidity()、reportValidity() 等方法),滿足進階的驗證需求。最後,文末的問與答單元會解答表單驗證的常見疑問,例如 HTML5 驗證與 JavaScript 驗證的差異、如何阻止表單送出、如何客製錯誤訊息,以及是否仍需要後端驗證等問題。
必填欄位:required
required 屬性用於指定表單欄位為必填欄位。當元素被標記為 required 時,如果使用者未填寫內容,瀏覽器將阻止表單送出,並提示該欄位「必須填寫」。此屬性本身為布林值屬性,僅需出現在標籤中即可生效(無需指定值)。
不同類型的表單元素使用 required 時,具體行為如下:
文字輸入欄位(如 <input type="text">、<input type="password"> 等)以及 文字區域(<textarea>):欄位不可留空,必須輸入內容。
核取方塊(<input type="checkbox">):必須勾選(選中)此方塊。常用於「我同意條款」等需強制確認的項目。
單選按鈕(<input type="radio">):同一組單選按鈕中至少要選取一個選項。只需對同 name 組中的其中一個 radio 加上 required,即可要求該組不可全都留空。
下拉選單(<select>):使用者必須選擇一個選項。如果下拉選單預設有一個空白或提示用的選項,標記 required 可確保使用者改選其他有效選項。
下面範例示範了一個文字欄位和一個下拉選單的必填設定。若其中一個未填,按「送出」時瀏覽器將跳出提示,要求使用者完成該欄位:
<form>
姓名:<input type="text" name="name" required><br>
國籍:
<select name="country" required>
<option value="">-- 請選擇 --</option>
<option value="TW">台灣</option>
<option value="JP">日本</option>
<option value="US">美國</option>
</select><br>
<input type="submit" value="送出">
</form>
在上述範例中,如果使用者未填寫姓名或未選擇國籍,點擊「送出」時表單將無法提交,瀏覽器會自動在該欄位旁顯示預設的錯誤提示(通常會顯示「請填寫此欄位」之類的訊息)。
格式模式:pattern
pattern 屬性允許為輸入欄位指定一個正規表達式(Regular Expression)模式。當表單提交時,瀏覽器會依據此正規表達式檢查欄位的值,只有格式完全匹配才算通過驗證。這對於驗證特殊格式的輸入非常有用,例如驗證用戶名只能包含字母和數字、電話號碼符合特定格式等等。
使用 pattern 屬性需要注意以下幾點:
pattern 的值是一個正規表達式字串,不包含開頭的 / 和結尾的 /。瀏覽器會將整個輸入值與此表達式進行比對(相當於正則的 ^...$ 全字串比對模式)。
pattern 只適用於文字類型的輸入框,例如 text、password、email、tel、url 等 <input>。它不適用於 <textarea> 或 <select> 元素(textarea 沒有 pattern 屬性)。
如果欄位有設置 required 或本身有值,且其值不符合 pattern 所定義的格式,表單將被阻止提交,瀏覽器會視為驗證不通過並顯示錯誤訊息。
如果欄位為空而沒有設定 required,則不會套用 pattern 驗證。也就是說,空值會被視為有效(因為未要求必填)。
可以搭配 title 屬性為欄位提供格式說明。部分瀏覽器在輸入格式錯誤時,會將 title 的內容一起顯示,幫助使用者了解正確的輸入格式。
範例:限制「用戶名」只能包含英文字母和數字,且長度在 4 到 10 個字元之間:
<form>
用戶名:<input type="text" name="username" pattern="[A-Za-z0-9]{4,10}" required
placeholder="4-10 位英數組合">
<input type="submit" value="送出">
</form>
在這個例子中,pattern="[A-Za-z0-9]{4,10}" 定義了允許的格式(4~10 個英文字母或數字)。搭配 required,表示欄位不可空白且必須符合格式。如果使用者輸入不符合要求,例如包含了其他符號或長度不足,表單將無法提交,並顯示瀏覽器預設的錯誤訊息(通常會提到不匹配所需的格式)。
數值範圍與步進:min、max、step
對於數字以及日期/時間類型的輸入,我們可以使用 min 和 max 屬性設定允許的最小值與最大值,並透過 step 屬性定義可接受值的步進間隔。這些屬性通常應用在 <input type="number">、<input type="range">、以及日期時間相關的 <input>(如 date、datetime-local、month、week、time)上。
重要事項如下:
min:定義欄位可接受的最小值。如果使用者輸入的值小於此值,將無法通過驗證。例如 min="0" 可確保輸入不得低於 0。
max:定義可接受的最大值。若輸入值大於此值,驗證不通過。例如 max="100" 表示值不可超過 100。
step:定義允許的數值間隔「步長」。瀏覽器的數字微調控制(如數字欄位的上下箭頭或 range 滑桿移動)將以此間隔增減數值。例如 step="5" 表示只接受 5 的倍數值。對於不整值的需求,可以使用小數或特殊值 any(允許任意間隔)。如果輸入的值不符合步進間隔(例如不在允許的倍數上),也會被視為無效。
min、max、step 通常一起使用來限定數字範圍。例如可以限制輸入範圍 1~10、且必須是偶數等等(透過調整 step)。
若欄位沒有輸入值且未標示 required,則不會因為違反 min/max/step 而報錯(空值視為可接受)。
這些屬性對數值型和日期型的輸入有效,但對純文字輸入無直接作用(如 <input type="text"> 設了 min 也不會生效)。例如,<input type="number"> 可使用 min/max,但 <input type="text"> 就無法理解數值範圍限制。
範例:以下顯示一個數字輸入欄位和一個範圍滑桿,各自設置了範圍和步進值:
<form>
數量:<input type="number" name="qty" min="1" max="10" step="1" value="5"><br>
亮度:<input type="range" name="bright" min="0" max="100" step="5" value="50"><br>
<input type="submit" value="送出">
</form>
在上例中,「數量」欄位限制只能輸入 1~10 的整數;「亮度」滑桿則可在 0~100 間以 5 為單位調整。如果使用者嘗試輸入不符合條件的值(例如將數量設為 0 或 15,或是透過其它手段輸入非 5 的倍數),表單將無法提交。對於數字欄位,瀏覽器可能也會在介面上禁止不合法的操作(例如在值已達到 min 或 max 時,對應方向的調整按鈕會停用)。另外,若要允許任何精度的數值輸入(例如允許小數點任意位數),可以將 step="any"。
輸入類型:type
HTML5 定義了許多新的輸入 type 類型,每種都有特定的行為和內建驗證規則。善用正確的輸入類型,能夠讓瀏覽器自動執行對應的格式檢查,並在行動裝置上調出適當的輸入介面。以下列出幾個常用的 input 類型及其驗證特性:
email:電子郵件地址欄位。要求輸入內容符合 Email 格式,包含「@」以及有效的網域等。如果格式不對(例如缺少 @),則視為無效。
url:網址欄位。要求輸入為一個有效的 URL,一般需要包含協定(例如 https://)。若格式不符標準 URL(如缺少協定或域名格式不正確),會被判定無效。
number:數字輸入欄位。僅能輸入數字(包括小數、正負號等)。非數字的內容無法輸入或會導致驗證失敗。可搭配 min、max、step 等屬性限定允許範圍和步進。
range:數值範圍選擇(滑桿)。它其實也是數字輸入的一種,以圖形滑桿呈現,用戶無法輸入文本只能拖動滑桿。可用 min、max、step 來定義範圍和刻度。輸出的值為數字,且受這些屬性限制。
date / datetime-local / month / week / time:日期與時間類型欄位。這些類型會啟用瀏覽器內建的日期/時間選擇介面,並且要求輸入值是有效的日期或時間格式(例如 YYYY-MM-DD 對 date)。如果輸入一個不合法的日期字串,表單也無法提交。
tel:電話號碼欄位。這類型不會執行格式驗證(因為各地電話號碼格式差異大),但在行動裝置上會調出電話鍵盤,方便輸入數字。
color:顏色選擇欄位。點擊時會跳出瀏覽器內建的調色盤。輸入的值必須是七位十六進位色碼(例如 "#ff0000")。如果手動輸入一個無效的色碼字串,將不通過驗證。
checkbox / radio:核取方塊與單選按鈕。這些類型本身不針對「值」進行格式驗證,因為它們的值通常是固定的(由 value 屬性決定)。不過可以配合 required 等屬性來要求是否選取。
file:檔案上傳欄位。允許使用者選擇檔案作為輸入。雖然無「內容格式」可驗證,但可透過 accept 屬性限制可選檔案的類型(例如 accept="image/*" 只允許影像檔)。也可以使用 multiple 屬性讓使用者一次選取多個檔案。
範例:下面的表單使用了 email 與 url 類型。Email 欄位若未填或格式不正確,送出時會被瀏覽器阻止;URL 欄位若格式不是有效網址也會驗證失敗。
<form>
電子郵件:<input type="email" name="userEmail" required><br>
個人網站:<input type="url" name="homepage"><br>
<input type="submit" value="送出">
</form>
上例中,Email 欄位有 required,因此必填且必須為有效的電子郵件格式;網站欄位未標記 required,允許空白,但如果填寫則需是合法網址格式。透過定義適當的 type,瀏覽器會自動提供相應的驗證行為和輸入體驗(例如行動裝置上,email 類型會出現含「@」的特殊鍵盤)。
長度限制:maxlength 和 minlength
maxlength 和 minlength 屬性用於限制文字輸入的長度範圍。前者設定最大允許長度,後者設定最小需求長度(皆以字元數計算)。
說明要點:
maxlength:最大字元數限制。使用者在輸入時,超過此長度的內容將被阻止繼續輸入(在大多數現代瀏覽器中會自動截斷超出的字元)。例如 maxlength="100" 代表最多輸入 100 個字。
minlength:最小字元數限制。表單提交時,若實際輸入長度少於此值,該欄位將被視為無效,提交會被阻止。例如 minlength="10" 表示至少要輸入 10 個字元才能通過驗證。
這兩個屬性適用於文字輸入類的元素,包括 <input type="text">、<input type="password">、<input type="email"> 等,以及 <textarea>。對於非文字輸入(如 number、range),maxlength/minlength 沒有作用(數字欄位的長度通常由其數值範圍決定)。
如果欄位未輸入任何值且未設為 required,minlength 的限制不會觸發。也就是說,空值在非必填的情況下可被接受,哪怕長度為 0 低於 minlength。
maxlength 的限制主要體現在前端輸入過程中,不會限制透過腳本設置的值長度(例如用 JavaScript 賦值給 input,即使超過 maxlength 瀏覽器也不會自行截斷)。因此,重要的長度限制仍應在後端再次驗證,以確保安全。
當長度超出 maxlength 或不足 minlength 時,瀏覽器會阻止表單提交,並顯示預設的錯誤訊息。例如,對 minlength 違規的欄位,Chrome 瀏覽器通常提示「請再輸入幾個字元」。
範例:以下是一個留言文字區域,限制最少輸入 10 個字、最多不超過 200 個字:
<form>
留言:<textarea name="message" minlength="10" maxlength="200" required
placeholder="請輸入10~200字的留言"></textarea>
<input type="submit" value="送出">
</form>
在這個例子中,留言欄位設定為必填,且字數需在 10 到 200 之間。如果使用者輸入少於 10 個字,表單提交時會被擋下並提示需要再多輸入一些內容;超過 200 字的部分則無法繼續輸入。maxlength 的作用是當場限制輸入,而 minlength 則是在提交時驗證長度是否達標。
多重輸入:multiple
multiple 屬性允許一個輸入欄位提供多筆值。常見應用場景包括讓使用者一次選取多個檔案,或在單一輸入框中輸入多個電子郵件地址。
重點說明:
multiple 是一個布林屬性,添加在相關的表單元素上即可啟用「多選/多值」能力。
對於 <input type="email">,加上 multiple 後,使用者可以在同一欄位輸入多個 Email 地址,各地址之間以逗號或分號分隔。瀏覽器會逐一驗證每個 Email 格式是否有效,只有所有地址都符合格式時整個欄位才通過驗證。
對於 <input type="file">,加上 multiple 屬性可讓使用者在檔案選擇對話框中選取多個檔案。選取後,input.files 會包含所有選擇的檔案列表。
multiple 屬性也可以用在 <select> 元素上,表示列表可以多選(會顯示為清單框而非下拉選單)。這不屬於「驗證」範疇,但提供了多選功能。搭配 required 使用時,表示使用者至少要選擇一項(否則算未填)。
若一個欄位同時標記了 multiple 和 required,則在驗證時需要至少有一個值存在(至少選了一個檔案或輸入了一個項目)。例如多重 Email 欄位 required 時,至少要填入一個 Email。
在 multiple 模式下(特別是 email),每一個輸入的值都必須有效。舉例來說,三個 Email 地址中若有一個格式錯誤,整個欄位會被判為無效。
範例:一個檔案上傳欄位允許多檔上傳,以及一個可輸入多個 Email 的欄位:
<form>
上傳圖片:<input type="file" name="photos" accept="image/*" multiple required><br>
通知信箱:<input type="email" name="emails" multiple
placeholder="可輸入多個Email,請以逗號分隔"><br>
<input type="submit" value="送出">
</form>
上述範例中,「上傳圖片」欄位透過 multiple 允許一次選擇多張圖片,並加上 required 確保至少選擇一個檔案;「通知信箱」欄位則可輸入多個電子郵件地址(以逗號分隔),但並未設為必填。使用者如果輸入了多個 Email,其中任一個不符合格式,表單提交會被阻止並提示格式錯誤。
唯讀與停用:readonly 和 disabled
有些場合我們希望表單欄位是只讀(僅供顯示,不允許編輯)或禁用(不允許使用者互動)。這時可以使用 readonly 或 disabled 屬性。兩者都會使欄位無法被使用者更改,但其行為有所不同:
readonly(唯讀):將欄位設定為唯讀狀態。使用者無法修改欄位中的值,但仍然可以點選欄位、將焦點移入以及複製其中的文字。唯讀欄位在表單提交時會包含其值。readonly 通常用於在表單中顯示計算所得或預先填好的資訊,但不允許使用者改動。
disabled(停用):將欄位停用。停用狀態的欄位在介面上通常呈灰色,使用者無法點選、聚焦或修改該欄位。更重要的是,disabled 欄位在提交時不會被包含在表單資料中(就彷彿這個欄位不存在一樣)。此外,瀏覽器在進行驗證時會跳過所有被 disabled 的欄位——例如即便有 required,設為 disabled 後也不會觸發必填檢查。
如果需要臨時地讓某欄位不可編輯,同時又希望保留其值提交給後端,可以使用 readonly。而如果不希望使用者與欄位有任何互動、且提交時也不需要該值,就使用 disabled。
例外:<select> 元素沒有 readonly 屬性,只能使用 disabled 來讓選單不可用。<textarea> 則和輸入框一樣支援 readonly 和 disabled。
範例:以下兩個文字輸入框分別示範唯讀和停用狀態:
唯讀欄位:<input type="text" value="只能讀取這段文字" readonly><br>
停用欄位:<input type="text" value="這段文字無法編輯" disabled>
在上例中,「唯讀欄位」中的文字使用者無法修改,但可以反白複製,提交表單時該值會被送出;「停用欄位」完全無法點擊或編輯,而且就算提交表單,這個欄位的值也不會包含在送出的資料中。開發者可以根據需求(例如依某些條件啟用/停用欄位)動態切換這些屬性。
停用驗證:novalidate 和 formnovalidate
有時候我們並不希望使用瀏覽器內建的驗證機制,可能因為要自行處理驗證邏輯,或是表單有多個提交按鈕(如「存為草稿」不需要填完所有欄位)。HTML5 提供了兩個屬性來關閉自動驗證:
novalidate:加在 <form> 表單標籤上時,會關閉該表單的所有 HTML5 驗證機制。也就是說,無論表單內有無違反上述驗證屬性的欄位,瀏覽器都會照常提交表單,不會跳出錯誤提示。這對需要自行用 JavaScript 驗證或完全依賴後端驗證的情況很有用。用法示例:<form action="/submit" novalidate> ... </form>。
formnovalidate:加在表單中的特定提交按鈕(例如 <button type="submit"> 或 <input type="submit">)上,用來在按下此按鈕時跳過驗證。通常用在有多個提交動作的表單,例如一個表單裡有「正式提交」和「儲存草稿」兩個按鈕:正式提交需要驗證所有欄位,而儲存草稿可以不經驗證就提交。將 formnovalidate 加在「儲存草稿」按鈕上,即可實現只跳過那一次的驗證。
下面範例展示同一表單中兩個提交按鈕的用法:一個正常驗證,另一個使用 formnovalidate 來略過驗證。
<form action="/submit">
姓名:<input type="text" name="name" required><br>
<button type="submit">提交表單</button>
<button type="submit" formnovalidate>儲存草稿</button>
</form>
在這個表單中,姓名欄位是必填。使用者點擊「提交表單」按鈕時,瀏覽器會檢查姓名是否填寫,若為空則阻止提交並提示錯誤。反之,使用者點擊「儲存草稿」按鈕時,儘管姓名可能沒填,表單也會直接提交(因為此按鈕標記了 formnovalidate,跳過了驗證步驟)。注意:如果 <form> 本身已經使用 novalidate 關閉驗證,則所有提交都不會驗證,formnovalidate 在那種情況下也沒有意義了。
JavaScript 自訂驗證
以上介紹的 HTML5 原生驗證屬性,大多能涵蓋一般的表單需求。然而,當我們需要更複雜的邏輯(例如跨欄位的驗證)、或要客製化錯誤訊息與樣式時,就需要透過 JavaScript 與瀏覽器的驗證 API 配合。
HTML5 提供了所謂約束驗證 API(Constraint Validation API),讓開發者可以用程式碼來檢查欄位有效性、設定自訂錯誤,以及手動啟動驗證等。常用的介面包括:
element.checkValidity() – 檢查某個表單控件是否通過所有驗證約束。回傳一個布林值,true 代表目前值是有效的、false 則代表未通過驗證。如果返回 false,瀏覽器同時會觸發該元素的 invalid 事件(可用來攔截預設行為)。
element.reportValidity() – 在進行 checkValidity() 檢查的同時,若發現無效則直接向使用者顯示瀏覽器內建的錯誤提示。對單一元素調用時,會立即顯示該元素的錯誤訊息;對 <form> 調用時,瀏覽器會自動尋找表單中第一個無效的欄位進行聚焦並顯示錯誤提示。該方法也會回傳布林值表示表單是否有效。
element.setCustomValidity(msg) – 設定自訂的驗證錯誤訊息。傳入一個非空字串將使該欄位變為無效狀態,並在驗證時使用此字串作為錯誤提示;傳入空字串則清除先前設定的自訂錯誤,恢復欄位的有效狀態(前提是沒有其他驗證錯誤)。
下面透過範例來說明如何運用這些方法進行自訂驗證。假設表單中有兩個「密碼」欄位,需要驗證兩者輸入一致,否則表單不能提交;此外我們也希望在提交前檢查整個表單的有效性,並即時向使用者報告所有錯誤。
<form id="signupForm">
密碼:<input type="password" id="pass1" name="pass1" required><br>
確認密碼:<input type="password" id="pass2" name="pass2" required><br>
電子郵件:<input type="email" id="emailField" name="email" required><br>
<button type="submit">送出</button>
</form>
<script>
const form = document.getElementById('signupForm');
const pass1 = document.getElementById('pass1');
const pass2 = document.getElementById('pass2');
const emailField = document.getElementById('emailField');
// 即時驗證兩次密碼是否一致
function validatePasswordMatch() {
if (pass1.value && pass2.value && pass1.value !== pass2.value) {
// 設定自訂錯誤訊息
pass2.setCustomValidity("兩次輸入的密碼不一致");
} else {
// 清除錯誤訊息
pass2.setCustomValidity("");
}
}
// 在用戶輸入時檢查密碼一致性
pass1.addEventListener('input', validatePasswordMatch);
pass2.addEventListener('input', validatePasswordMatch);
// 提交表單時檢查整體有效性
form.addEventListener('submit', (event) => {
// 先清除可能殘留的自訂錯誤(例如之前密碼不一致的訊息)
validatePasswordMatch();
// 使用 checkValidity 檢查整個表單
if (!form.checkValidity()) {
// 若有任一欄位無效,阻止表單提交
event.preventDefault();
// 使用 reportValidity 顯示錯誤訊息(觸發瀏覽器報錯 UI)
form.reportValidity();
}
});
</script>
上述程式碼做了以下幾件事:
在密碼和確認密碼欄位的輸入事件中,調用 setCustomValidity() 來自訂驗證:當兩次密碼不相同時,對第二個密碼欄位設定一則錯誤訊息「兩次輸入的密碼不一致」,並將欄位標記為無效;反之則清除錯誤,使其恢復可提交狀態。這樣用戶一旦輸入不一致,瀏覽器就記住了這個自訂錯誤。在修正前(或者錯誤被清除前),即使兩個欄位都填了內容,表單仍會視確認密碼欄位為無效。
在表單提交 (submit) 事件發生時,首先再次執行一次 validatePasswordMatch(),確保在最新輸入狀況下我們的自訂錯誤正確設定。接著調用 form.checkValidity() 檢查整個表單。如果返回 false,表示至少有一個欄位未通過驗證,這時我們透過 event.preventDefault() 阻止表單的送出。
然後,使用 form.reportValidity() 來觸發瀏覽器將所有驗證錯誤顯示給使用者。reportValidity() 會自動聚焦到第一個有問題的欄位並顯示該欄位的錯誤提示(例如:若確認密碼不一致,會顯示我們設定的「兩次輸入的密碼不一致」;如果密碼一致但 Email 欄位格式不正確,則會聚焦 Email 欄位並顯示瀏覽器預設的 Email 格式錯誤提示)。
值得注意的是,我們並沒有對 Email 欄位手動設定任何自訂錯誤,因為 HTML5 內建的 Email 格式驗證已足夠。checkValidity() 會檢查 Email 欄位的 type="email" 規則,如果格式不對會返回 false,而 reportValidity() 則會讓瀏覽器用預設訊息(例如「請輸入有效的電子郵件地址」)提醒使用者。
透過以上方式,我們實現了自訂驗證與 HTML5 原生驗證的結合:密碼匹配的規則由我們自訂,Email 等其他規則則沿用瀏覽器內建檢查,在使用者提交時綜合判定。總結來說,checkValidity() 和 reportValidity() 常用於在 JavaScript 中手動觸發整體驗證流程,而 setCustomValidity() 則用於定製單個欄位的驗證規則與訊息。
常見問題解答
問:HTML5 原生驗證和 JavaScript 驗證有何差別?
答: HTML5 原生驗證是由瀏覽器自動執行的,開發者只需在標籤上設定相應屬性(如 required、pattern 等),瀏覽器會在提交時進行檢查並提供預設的錯誤提示,好處是實作簡單、即時性高。但原生驗證的客製化程度有限,提示訊息樣式和行為依瀏覽器而定。JavaScript 驗證則是由開發者自行撰寫程式來檢查輸入,彈性高,可以實現更複雜的驗證規則與自訂訊息,控制權更高。實務上常兩者搭配使用:前端先利用 HTML5 驗證提供基本的即時回饋,再以 JS 強化特殊邏輯和使用者體驗;而不論如何,後端驗證仍是必要,因為使用者能夠繞過前端的限制(詳見下題)。
問:如何阻止表單送出(提交)?
答: 一般來說,若表單欄位未通過 HTML5 驗證,瀏覽器會自動阻止提交,不需額外程式碼。如果要在程式中手動控制表單提交(例如根據其他條件取消提交),可以使用 JavaScript 攔截提交事件。最常見的方法是在表單的提交事件中呼叫 event.preventDefault()。例如:
form.addEventListener('submit', function(event) {
if (!form.checkValidity()) {
// 某些欄位未通過驗證,阻止表單送出
event.preventDefault();
form.reportValidity(); // 顯示錯誤提示
}
});
上面程式碼會在表單提交時檢查 form.checkValidity(),如果結果為 false(代表尚有欄位未通過驗證),則呼叫 event.preventDefault() 阻止這次提交。如此使用者按下送出按鈕也不會跳轉頁面。搭配 reportValidity(),我們還可以立即顯示所有錯誤提示,提醒使用者哪裡需要修正。另一種簡易做法是利用表單的 onsubmit 屬性:例如 <form onsubmit="return false"> 會在任何情況下都阻止提交。但通常我們會在條件判斷中有選擇地 return false 或 preventDefault,以便在符合某些條件時才取消提交。
問:如何自訂驗證的錯誤訊息?
答: 可以利用 HTML5 的驗證 API 來設定自訂錯誤訊息,最直接的方法是調用表單元素的 setCustomValidity() 方法。當偵測到特定條件不符時,對該元素呼叫例如 emailInput.setCustomValidity("請輸入有效的電子郵件地址");,即可將自訂訊息指定給它。這行程式會讓 emailInput 欄位在驗證時顯示「請輸入有效的電子郵件地址」的提示,而不是瀏覽器原本的預設提示。當條件恢復正常時,記得呼叫 emailInput.setCustomValidity("") 清除錯誤狀態,不然欄位即使內容有效也會因殘留舊訊息而無法提交。
除了 setCustomValidity 之外,另一種方式是自行呈現錯誤訊息:可以將表單標記為 novalidate,完全由 JavaScript 接管驗證流程,然後將錯誤訊息直接插入到網頁中(例如放在欄位下方,以紅色文字顯示)。這種做法需要自行處理更多邏輯和樣式,但可以完全掌控訊息的呈現。需要注意的是,瀏覽器內建的錯誤提示(工具提示泡泡)無法直接用 CSS 修改。如果想改變其外觀或語言,就只能採取自訂渲染訊息的方式。
問:使用 HTML5 驗證後,還有必要進行後端驗證嗎?
答: 絕對有必要。 前端(無論 HTML5 或 JS)的驗證只能提高使用者體驗,避免大部分明顯的錯誤輸入,但它不能取代後端驗證。使用者仍可能透過停用 JavaScript、竄改表單等方式繞過前端驗證。因此,後端必須對收到的資料再次進行嚴格的驗證和清理。一旦前端驗證被跳過,後端是最後的防線。例如,即使表單欄位標示了 type="number",惡意使用者仍可能提交非數字的值到伺服器端,後端若沒有檢查就直接接受,將造成潛在風險。總之,前端驗證屬於方便使用者的機制,後端驗證才是保障資料正確與系統安全的關鍵,兩者缺一不可。