檔案上傳 (File Upload)

  • 新提案
  • 封閉測試
  • 公開測試
  • 已穩定
成熟度說明
  • 新提案:未完成開發、請勿使用。
  • 封閉測試:開發暫時性完成,可使用。可能仍有親和力或其他使用上問題待透過實測發現。
  • 公開測試:開發暫時性完成,歡迎使用。具有完整親和力報告。
  • 已穩定:開發完成、歡迎使用。應無任何親和力或使用上問題。

說明

  • 檔案上傳(File Upload)讓使用者選擇本機檔案並上傳至系統,支援以「點擊選擇」或「拖曳至上傳區」兩種方式選取檔案。
  • 視覺風格方形虛線拖放區搭配 outline 樣式的「選擇檔案」按鈕,並保留 HTML 原生 input 的可及性與功能。

預設

支援 PDF、JPG、PNG 格式,單一檔案大小不得超過 10MB。

HTML
<div class="fieldset">
  <label for="fu-default" class="field-label">附件上傳</label>
  <p id="fu-default-hint" class="field-hint">支援 PDF、JPG、PNG 格式,單一檔案大小不得超過 10MB。</p>
  <div class="file-upload">
    <input type="file" id="fu-default" class="file-upload__input" aria-describedby="fu-default-hint">
    <div class="file-upload__dropzone" aria-hidden="true">
      <span class="file-upload__button">選擇檔案</span>
      <span class="file-upload__instruction">或將檔案拖曳至此處</span>
    </div>
  </div>
</div>

多檔案上傳

支援 PDF、JPG、PNG 格式,每個檔案不得超過 10MB,最多可上傳 5 個檔案。

HTML
<div class="fieldset">
  <label for="fu-multi" class="field-label">證明文件(可選擇多個檔案)</label>
  <p id="fu-multi-hint" class="field-hint">支援 PDF、JPG、PNG 格式,每個檔案不得超過 10MB,最多可上傳 5 個檔案。</p>
  <div class="file-upload">
    <input type="file" id="fu-multi" class="file-upload__input" multiple accept=".pdf,.jpg,.jpeg,.png" aria-describedby="fu-multi-hint">
    <div class="file-upload__dropzone" aria-hidden="true">
      <span class="file-upload__button">選擇檔案</span>
      <span class="file-upload__instruction">或將多個檔案拖曳至此處</span>
    </div>
  </div>
</div>

已選取檔案的呈現

選取後以清單呈現所選檔案,每個項目提供「移除」按鈕。實際應用時需以 JavaScript 監聽 change 事件,動態更新清單。

支援 PDF、JPG、PNG 格式,每個檔案不得超過 10MB。

  • 身分證正面.jpg (256 KB)
  • 身分證背面.jpg (212 KB)
HTML
<div class="fieldset">
  <label for="fu-selected" class="field-label">證明文件(已選擇)</label>
  <p id="fu-selected-hint" class="field-hint">支援 PDF、JPG、PNG 格式,每個檔案不得超過 10MB。</p>
  <div class="file-upload file-upload--has-files">
    <input type="file" id="fu-selected" class="file-upload__input" multiple aria-describedby="fu-selected-hint">
    <div class="file-upload__dropzone" aria-hidden="true">
      <span class="file-upload__button">變更檔案</span>
      <span class="file-upload__instruction">或將檔案拖曳至此處</span>
    </div>
  </div>
  <ul class="file-upload__file-list" aria-label="已選擇的檔案">
    <li class="file-upload__file">
      <span class="file-upload__file-icon" aria-hidden="true">📄</span>
      <span class="file-upload__file-name">身分證正面.jpg</span>
      <span class="file-upload__file-size">(256 KB)</span>
      <button type="button" class="file-upload__file-remove" aria-label="移除檔案:身分證正面.jpg">移除</button>
    </li>
    <li class="file-upload__file">
      <span class="file-upload__file-icon" aria-hidden="true">📄</span>
      <span class="file-upload__file-name">身分證背面.jpg</span>
      <span class="file-upload__file-size">(212 KB)</span>
      <button type="button" class="file-upload__file-remove" aria-label="移除檔案:身分證背面.jpg">移除</button>
    </li>
  </ul>
</div>

錯誤狀態

支援 PDF、JPG、PNG 格式,單一檔案大小不得超過 10MB。

錯誤:所選檔案大小超過 10MB,請選擇較小的檔案。

HTML
<div class="fieldset fieldset-has-error">
  <label for="fu-error" class="field-label">附件上傳</label>
  <p id="fu-error-hint" class="field-hint">支援 PDF、JPG、PNG 格式,單一檔案大小不得超過 10MB。</p>
  <p id="fu-error-msg" class="field-error">
    <span class="field-error__prefix">錯誤:</span>所選檔案大小超過 10MB,請選擇較小的檔案。
  </p>
  <div class="file-upload file-upload--error">
    <input type="file" id="fu-error" class="file-upload__input" aria-describedby="fu-error-hint fu-error-msg" aria-invalid="true">
    <div class="file-upload__dropzone" aria-hidden="true">
      <span class="file-upload__button">選擇檔案</span>
      <span class="file-upload__instruction">或將檔案拖曳至此處</span>
    </div>
  </div>
</div>

CSS

  • .file-upload:拖放區外層容器。
  • .file-upload__input:原生 <input type="file">,以絕對定位覆蓋整個拖放區、視覺透明,但仍是真正的互動元素。
  • .file-upload__dropzone:拖放區內視覺裝飾內容,以 aria-hidden="true" 隱藏避免重複朗讀。
  • .file-upload__button:仿造按鈕外觀的 <span>,僅供視覺呈現。
  • .file-upload__instruction:拖放說明文字。
  • .file-upload--error:錯誤狀態,搭配 .fieldset-has-error.field-error 使用。
  • .file-upload--has-files:已選擇檔案後的樣式。
  • .file-upload__file-list/.file-upload__file:已選檔案清單與單一項目。
  • .file-upload__file-remove:移除單一檔案的按鈕。

使用規範

  • 必要時才要求上傳:上傳對使用者而言成本較高,僅在流程確實需要時才使用。
  • 明確告知限制:在 field-hint 中清楚列出可接受的檔案類型、單檔大小上限、檔案數量上限。
  • 同時支援點擊與拖曳:拖放區同時支援滑鼠點擊、鍵盤觸發、拖曳放置三種互動方式。
  • 多檔案請使用 multiple:在 <input> 加上 multiple 屬性即可支援;說明文字也應同步更新為複數。
  • 限制檔案類型用 accept:例如 accept=".pdf,.jpg,.png";但仍須在伺服器端驗證,因為 accept 僅為前端篩選提示。
  • 錯誤訊息要明確:說明錯誤原因與下一步該怎麼做,例如「所選檔案大小超過 10MB,請選擇較小的檔案」。

親和力

  • 保留原生 Input:所有自訂視覺外觀皆建構於原生 <input> 之上,並以絕對定位 + opacity: 0 覆蓋整個拖放區,使其同時:
    • 接收滑鼠點擊以開啟系統檔案對話框
    • 原生支援拖曳放置
    • <label> 提供無障礙名稱,螢幕報讀軟體會朗讀「選擇檔案 按鈕,未選擇任何檔案」
    • 受鍵盤焦點,並由 :focus-within 將焦點輪廓延伸至視覺按鈕
  • 裝飾內容以 aria-hidden="true" 隱藏:拖放區內的視覺按鈕與「拖曳至此」說明文字,對螢幕報讀軟體而言會與 <input> 本身的朗讀重複,因此整個 .file-upload__dropzone 加上 aria-hidden="true",避免雙重朗讀。
  • 使用 aria-describedby 連結提示與錯誤訊息:說明檔案類型大小限制的提示文字、以及錯誤訊息,皆以 aria-describedby 連結至 <input>,讓螢幕報讀軟體在朗讀欄位時一併朗讀。
  • 錯誤狀態以 aria-invalid="true" 標示:搭配視覺紅色邊框與「錯誤:」前綴文字,避免僅以顏色傳達錯誤狀態。
  • 點擊目標 ≥ 2.5rem:拖放區、按鈕、移除按鈕的點擊目標皆不小於 2.5rem × 2.5rem。
  • 明顯的焦點外觀:以 :focus-within 同時提示拖放區與內部視覺按鈕。
  • 語音控制(Voice control)友善:可見的「選擇檔案」文字與 <label> 文字一致,使用者可直接以語音指令啟動。
  • 已選擇檔案以 <ul aria-label> 呈現:螢幕報讀軟體可朗讀「已選擇的檔案,清單,共 N 項」,並可逐一朗讀檔名與大小。
  • 「移除」按鈕補上完整 aria-label:例如「移除檔案:身分證正面.jpg」,避免僅朗讀「移除」造成混淆。
  • 漸進增強原則:自訂行為(檔案清單、客製錯誤訊息、進度顯示)皆建構於原生 <input type="file"> 之上;即使 JavaScript 失敗,使用者仍能以原生方式選擇與上傳檔案。

參考資料