17. 輸入控制元素 (Input Control Elements)

HTML 輸入控制元素讓使用者輸入資料、選擇選項,以及執行操作。

它們常見於搜尋、課程報名、檔案上載及發送查詢等表單。

常用控制元素包括:

元素用途
<input>文字、選項、日期、檔案及其他輸入類型
<textarea>多行文字
<select>從清單中選擇
<button>提交或執行其他操作
<label>識別控制元素
<fieldset>組合相關控制元素
<legend>為欄位群組提供名稱

按所需資料選擇控制元素,提供清晰標籤,並在可行的情況下使用原生 HTML 行為。

17.1 表單內的控制元素

<form> 將控制元素組合起來,用於收集及提交資料:

<form action="/course-enquiries" method="post">
  <label for="full-name">姓名</label>
  <input
    id="full-name"
    name="fullName"
    type="text"
    autocomplete="name"
    required
  >

  <button type="submit">發送查詢</button>
</form>

在這個例子中:

  • action 指定提交目的地。
  • method 指定表單的提交方法。
  • name 識別控制元素提交的值。
  • required 表示必須完成該欄位,才能通過原生驗證。

目的地必須具備適當的伺服器端處理功能。單靠 HTML 不會儲存查詢或發送電郵。

不要將一個 <form> 嵌套在另一個 <form> 內。

17.2 <input> 元素

<input> 是空元素,沒有結束標籤。

它的 type 決定輸入行為:

<input type="text" name="courseSearch">

省略 type 時,預設為 text。

常見類型包括:

類型常見用途
text單行文字
search搜尋字句
email電郵地址
password遮蔽顯示的文字輸入
tel電話號碼
url網址
number數值或數量
date日期
time時間
checkbox獨立選項
radio同一組內的單選選項
file選取檔案
range在刻度範圍內選擇數值
color選擇顏色
hidden不顯示的表單資料

不同瀏覽器及裝置的外觀和操作方式可能不同。

17.3 標籤、識別碼與名稱

可見的 <label> 告訴讀者控制元素的用途:

<label for="email-address">電郵地址</label>
<input
  id="email-address"
  name="email"
  type="email"
  autocomplete="email"
>

標籤的 for 值必須與輸入元素的 id 相同。

各屬性有不同職責:

  • id:識別元素,並將它與標籤連接。
  • name:識別提交時的資料值。
  • type:選擇輸入行為。

沒有 name 的控制元素,通常不會在表單提交中提供具名資料值。

點擊或輕觸已連接的標籤,也有助啟動控制元素或讓它取得焦點。

標籤也可以包住輸入元素:

<label>
  電郵地址
  <input name="email" type="email">
</label>

明確使用 for 與 id,通常更方便配合不同版面。

17.4 填寫說明與預留位置文字

填寫欄位時需要的資訊,應以可見說明提供:

<label for="display-name">顯示名稱</label>
<input
  id="display-name"
  name="displayName"
  type="text"
  maxlength="40"
  aria-describedby="display-name-help"
>
<p id="display-name-help">
  最多可輸入 40 個字元。
</p>

aria-describedby 將控制元素與補充文字連接起來。

placeholder 可以提供範例:

<label for="course-search">搜尋課程</label>
<input
  id="course-search"
  name="query"
  type="search"
  placeholder="例如:HTML"
>

預留位置文字不能取代標籤。 它會在輸入時消失,而且可能不容易閱讀。

17.5 文字、電郵、電話與密碼欄位

以下片段示範各類欄位的設定;實際使用時,每個欄位仍應有適當標籤。

一般文字

<input
  id="full-name"
  name="fullName"
  type="text"
  autocomplete="name"
>

避免對姓名設定不必要的嚴格格式。姓名可能包含空格、標點,以及不同書寫系統的字元。

電郵地址

<input
  id="email"
  name="email"
  type="email"
  autocomplete="email"
  required
>

type="email" 提供基本格式驗證,但不會證明地址存在,也不會確認地址屬於訪客。

電話號碼

<input
  id="telephone"
  name="telephone"
  type="tel"
  autocomplete="tel"
>

不同國家及地區的電話格式不同,因此 tel 不會強制使用統一格式。

密碼

<input
  id="account-password"
  name="password"
  type="password"
  autocomplete="new-password"
  required
>

密碼遮蔽只會改變顯示方式,不會加密提交的資料。

應使用 HTTPS 及適當的伺服器端安全措施。輸入現有帳戶的登入密碼時,使用 autocomplete="current-password"。

17.6 數值、日期與輸入提示

數量資料可以使用 number:

<label for="places">報名名額數量</label>
<input
  id="places"
  name="places"
  type="number"
  min="1"
  max="6"
  step="1"
  value="1"
>

不要只因資料包含數字,就使用數值欄位。電話號碼、郵政編碼及帳戶識別碼不是數量。

由數字組成的識別碼,可能更適合文字欄位配合鍵盤提示:

<input
  id="reference-code"
  name="referenceCode"
  type="text"
  inputmode="numeric"
>

inputmode 提示適合的輸入方式,例如數字鍵盤;它不會驗證資料值。

日期欄位:

<label for="preferred-date">首選日期</label>
<input
  id="preferred-date"
  name="preferredDate"
  type="date"
>

介面可能使用本地日期格式,但控制元素的值使用標準的年、月、日格式:YYYY-MM-DD。

17.7 使用 <textarea> 輸入多行文字

訊息及較長回覆可以使用 <textarea>:

<label for="message">你的訊息</label>
<textarea
  id="message"
  name="message"
  rows="5"
  maxlength="2000"
></textarea>

與 <input> 不同,<textarea> 需要結束標籤。

初始值放在標籤之間:

<textarea name="message" rows="5">我想查詢……</textarea>

不要使用 value 屬性設定初始文字。

應提供足夠的書寫空間,並避免在沒有充分理由下阻止使用者調整控制元素大小。

17.8 從清單中選擇

使用 <select> 和 <option> 提供選項清單:

<label for="course">課程</label>
<select id="course" name="course" required>
  <option value="">請選擇課程</option>
  <option value="html-basics">HTML 入門</option>
  <option value="css-basics">CSS 入門</option>
  <option value="javascript-basics">JavaScript 入門</option>
</select>

提交時會使用已選選項的 value。

對必填的單選清單,初始空值選項可以提示使用者作出明確選擇。

使用 selected 提供預設選項:

<option value="html-basics" selected>HTML 入門</option>

相關選項可以分組:

<select name="course">
  <optgroup label="入門程度">
    <option value="html-basics">HTML 入門</option>
    <option value="css-basics">CSS 入門</option>
  </optgroup>
</select>

multiple 允許選擇多項,但操作方式不一定清晰。對較短的清單,核取方塊可能更容易使用。

17.9 核取方塊

核取方塊表示獨立選項:

<label>
  <input
    type="checkbox"
    name="updates"
    value="yes"
  >
  向我發送課程最新資訊
</label>

未勾選的核取方塊,通常不會在提交時提供資料值。

已勾選的核取方塊會提交其 value。如果省略該屬性,預設提交值為 "on"。

使用 checked 設定初始勾選狀態:

<input type="checkbox" name="updates" value="yes" checked>

checked 是布林屬性。寫成 checked="false",仍然代表屬性存在,因此初始狀態仍是已勾選。

不要只為方便,就預先勾選非必要的同意選項。

17.10 單選按鈕與群組標籤

單選按鈕讓使用者在同一組中選擇一項。

相關單選按鈕應使用相同 name,以及不同的值:

<fieldset>
  <legend>首選上課時段</legend>

  <label>
    <input
      type="radio"
      name="session"
      value="morning"
      required
    >
    上午
  </label>

  <label>
    <input
      type="radio"
      name="session"
      value="afternoon"
      required
    >
    下午
  </label>
</fieldset>

<fieldset> 組合控制元素,<legend> 則為群組提供名稱。

只有已選取的單選按鈕值會提交。

每個單選按鈕仍然需要自己的標籤。群組的 <legend> 不能取代個別標籤。

17.11 檔案輸入欄位

使用 type="file" 讓訪客選擇檔案:

<label for="attachment">附加文件</label>
<input
  id="attachment"
  name="attachment"
  type="file"
  accept=".pdf"
>

accept 引導檔案選擇,但不能可靠地強制檔案類型,也不會令上載變得安全。

使用原生表單提交檔案時,表單需要以下設定:

<form
  action="/upload"
  method="post"
  enctype="multipart/form-data"
>
  <!-- 檔案控制元素及提交按鈕。 -->
</form>

伺服器必須驗證檔案大小、實際內容、權限及儲存處理方式。

檔案輸入欄位不能偷偷選取訪客電腦上的任意檔案。

17.12 按鈕及其類型

明確指定按鈕類型:

<button type="submit">發送查詢</button>
<button type="button">顯示說明</button>
<button type="reset">重設表單</button>
類型行為
submit提交所屬表單
button沒有預設提交操作
reset將控制元素還原至初始值

一般與表單關聯的 <button>,如果省略類型,會預設用作提交。

重設按鈕可能意外清除使用者的輸入,因此除非有明確需要,否則應避免提供。

17.13 驗證與控制狀態

HTML 提供基本限制驗證:

屬性用途
required必須提供值或作出適用的選擇
minlength / maxlength文字長度限制
min / max支援類型的數值或日期限制
step允許的步距
pattern支援的文字輸入類型所使用的正規表示式限制

應以可見文字說明限制,不要讓訪客只在發生錯誤後才發現要求。

停用與唯讀

<input name="courseCode" value="HTML-101" readonly>
<input name="unavailableOption" value="暫不提供" disabled>
  • readonly:阻止編輯適用的控制元素,但值仍然可以提交。
  • disabled:阻止一般操作,而且控制元素不會包含在提交資料中。

兩者都不能防止資料值被修改或偽造。

瀏覽器驗證可以改善操作體驗,但所有提交資料仍必須在伺服器端驗證。

17.14 完整範例:課程查詢控制元素

以下示範包含已標示的文字欄位、選項清單、單選按鈕、核取方塊及多行文字欄位。

它會在本頁驗證表單並顯示狀態訊息,不會發送或儲存查詢。

id: hong-kong-html-input-controls
name: 輸入控制元素 — 課程查詢示範
type: html
content: |-
  <!doctype html>
  <html lang="zh-Hant-HK">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>輸入控制元素 | 課程查詢示範</title>
    <style>
      *,
      *::before,
      *::after {
        box-sizing: border-box;
      }

      body {
        margin: 0;
        color: #222;
        background: #f5f7fa;
        font-family: system-ui, sans-serif;
        line-height: 1.8;
      }

      main {
        max-width: 42rem;
        margin-inline: auto;
        padding: 2rem 1rem;
      }

      h1 {
        color: #005ea8;
        line-height: 1.4;
      }

      form {
        padding: 1.25rem;
        border: 1px solid #767676;
        border-radius: 0.5rem;
        background: white;
      }

      .field {
        margin-block-end: 1.5rem;
      }

      .field > label,
      legend {
        font-weight: 700;
      }

      .field > label {
        display: block;
        margin-block-end: 0.4rem;
      }

      input:not([type="radio"]):not([type="checkbox"]),
      select,
      textarea {
        display: block;
        width: 100%;
        padding: 0.65rem;
        border: 1px solid #767676;
        border-radius: 0.25rem;
        color: #222;
        background: white;
        font: inherit;
      }

      textarea {
        resize: vertical;
        min-height: 8rem;
      }

      fieldset {
        min-width: 0;
        margin: 0 0 1.5rem;
        padding: 1rem;
        border: 1px solid #767676;
        border-radius: 0.25rem;
      }

      .choice {
        display: flex;
        align-items: flex-start;
        gap: 0.6rem;
        padding-block: 0.5rem;
      }

      .choice input {
        flex-shrink: 0;
        margin-block-start: 0.55rem;
      }

      .help {
        margin-block: 0.4rem 0;
        color: #4b5563;
      }

      .note {
        padding: 1rem;
        border-inline-start: 4px solid #005ea8;
        background: #eaf2f8;
      }

      button {
        padding: 0.65rem 1rem;
        border: 2px solid #005ea8;
        border-radius: 0.25rem;
        color: white;
        background: #005ea8;
        font: inherit;
        cursor: pointer;
      }

      button:disabled {
        color: #444;
        background: #e0e0e0;
        border-color: #767676;
        cursor: not-allowed;
      }

      input:focus-visible,
      select:focus-visible,
      textarea:focus-visible,
      button:focus-visible {
        outline: 3px solid #005ea8;
        outline-offset: 3px;
      }

      #demo-status {
        margin-block: 1rem 0;
      }
    </style>
  </head>
  <body>
    <main>
      <h1>課程查詢示範</h1>
      <p class="note">
        練習使用表單控制元素。
        本頁不會發送或儲存你輸入的資料。
        請使用範例資料,不要填寫個人資料。
      </p>

      <form id="enquiry-form">
        <p>標示「必填」或「必選」的項目必須完成。</p>

        <div class="field">
          <label for="full-name">姓名(必填)</label>
          <input
            id="full-name"
            name="fullName"
            type="text"
            autocomplete="name"
            required
          >
        </div>

        <div class="field">
          <label for="email">電郵地址(必填)</label>
          <input
            id="email"
            name="email"
            type="email"
            autocomplete="email"
            aria-describedby="email-help"
            required
          >
          <p id="email-help" class="help">
            此示範可以使用 [email protected]。
          </p>
        </div>

        <div class="field">
          <label for="course">課程(必選)</label>
          <select id="course" name="course" required>
            <option value="">請選擇課程</option>
            <option value="html-basics">HTML 入門</option>
            <option value="css-basics">CSS 入門</option>
            <option value="javascript-basics">JavaScript 入門</option>
          </select>
        </div>

        <fieldset>
          <legend>首選上課時段(必選)</legend>
          <label class="choice">
            <input
              type="radio"
              name="session"
              value="morning"
              required
            >
            <span>上午</span>
          </label>
          <label class="choice">
            <input
              type="radio"
              name="session"
              value="afternoon"
              required
            >
            <span>下午</span>
          </label>
        </fieldset>

        <div class="field">
          <label for="message">訊息(選填)</label>
          <textarea
            id="message"
            name="message"
            rows="5"
            maxlength="1000"
            aria-describedby="message-help"
          ></textarea>
          <p id="message-help" class="help">
            最多 1,000 個字元。請勿包含機密資料。
          </p>
        </div>

        <div class="field">
          <label class="choice">
            <input type="checkbox" name="updates" value="yes">
            <span>
              在這份範例查詢中選擇接收課程最新資訊(選填)
            </span>
          </label>
        </div>

        <button id="check-button" type="submit" disabled>
          檢查範例查詢
        </button>
        <p id="demo-status" role="status" aria-atomic="true">
          互動檢查功能需要 JavaScript。
        </p>
      </form>
    </main>

    <script>
      const form = document.getElementById("enquiry-form");
      const button = document.getElementById("check-button");
      const status = document.getElementById("demo-status");

      // 阻止提交,包括按 Enter 觸發的隱式提交。
      form.addEventListener("submit", (event) => {
        event.preventDefault();

        const data = new FormData(form);
        const updates = data.has("updates")
          ? "已選擇接收課程最新資訊。"
          : "未選擇接收課程最新資訊。";

        status.textContent =
          `範例查詢已通過瀏覽器驗證。${updates}` +
          "沒有發送或儲存任何資料。";
      });

      status.textContent =
        "已準備好檢查範例查詢,不會發送任何資料。";
      button.disabled = false;
    </script>
  </body>
  </html>

在這個範例中:

  • 標籤識別每個輸入控制元素。
  • name 屬性識別表單資料值。
  • <fieldset> 和 <legend> 將時段選項組合起來。
  • 原生驗證會在提交事件之前檢查必填欄位。
  • FormData 讀取目前的表單值。
  • JavaScript 阻止提交導覽,並顯示狀態訊息。
  • JavaScript 無法使用時,檢查按鈕會保持停用。

實際查詢服務需要適當的提交端點、伺服器端驗證、私隱說明,以及安全的資料處理。

17.15 常見錯誤

錯誤較好的做法
使用預留位置文字代替標籤提供持續可見的標籤
控制元素有 id,但沒有 name需要提交值時加入 name
使用數值欄位輸入電話號碼使用 tel
相關單選按鈕使用不同名稱使用相同的群組名稱
以為未勾選的核取方塊會提交 "false"明確處理該欄位沒有提交值的情況
使用 checked="false" 或 disabled="false"移除布林屬性以取消狀態
使用 value 設定多行文字的初始值將文字放在標籤之間
省略按鈕類型指定 submit、button 或 reset
將檔案選取提示視為安全檢查在伺服器端驗證上載檔案
以為密碼遮蔽會加密資料使用 HTTPS 及安全處理
只相信瀏覽器驗證在伺服器端驗證所有提交資料
不必要地建立自訂控制元素優先使用具備無障礙功能的原生元素

本章總結: 輸入控制元素收集文字、選項、檔案及其他資料值。使用適當類型、清晰標籤、有意義的群組,以及明確的按鈕行為。原生驗證有助使用者完成表單,但安全提交及權威驗證仍需要伺服器端處理。

Scroll to Top