無障礙設計(a11y):
讓每個人都能使用你的網站
ARIA 屬性、語義化 HTML、鍵盤導航、色彩對比 — 前端面試越來越常考,也是做好產品的必修課
Section 1:為什麼要做無障礙設計
根據 WHO 數據,全球約有 15% 的人口(約 13 億人)有某種形式的障礙。這包括視障(使用螢幕閱讀器)、聽障(需要字幕)、行動障礙(只能使用鍵盤或語音輸入)、以及認知障礙(需要清晰的排版與語言)。
受影響的族群
- 👁️視障:使用螢幕閱讀器(NVDA、VoiceOver)逐字聆聽頁面
- 👂聽障:影片需要字幕、不依賴聲音提示
- 🖐️行動障礙:只用鍵盤、語音、眼動儀操作
- 🧠認知障礙:需要簡單清晰的語言與結構
為什麼你應該在意
- 法律要求:美國 ADA、歐盟 EAA、台灣身心障礙者權益保障法
- SEO 提升:語義化 HTML 讓搜尋引擎更理解頁面結構
- 更大的用戶群:覆蓋更多用戶 = 更多潛在客戶
- 前端面試考點:越來越多企業在面試時詢問 a11y
斜坡效應(Curb Cut Effect)
無障礙設計不是特殊功能,而是正確的設計。就像路邊的斜坡,不只讓輪椅用戶受益,也讓推嬰兒車的家長、搬貨的工人都更方便。網頁上的鍵盤導航,不只服務行動障礙用戶,也讓喜歡鍵盤操作的工程師效率更高。
Section 2:語義化 HTML — 最低成本的無障礙
語義化 HTML 是無障礙設計的地基。螢幕閱讀器依賴 HTML 元素本身的「語義」來理解頁面結構,告訴用戶「這是一個導覽列」、「這是主要內容」、「這是一個按鈕」。使用正確的元素幾乎不需要額外程式碼,卻能大幅提升可訪問性。
壞 vs 好的 HTML 結構對比
常用語義化元素速查表
| 元素 | 用途與說明 |
|---|---|
| <header> | 頁面或區塊的頭部,可包含 Logo、導覽、搜尋列 |
| <nav> | 導覽連結群組,螢幕閱讀器會宣告「導覽區域」 |
| <main> | 主要內容(每頁只有一個),螢幕閱讀器可跳轉到此 |
| <article> | 獨立完整的內容單元,例如文章、卡片、留言 |
| <section> | 有標題的內容區塊,比 div 更有語義 |
| <aside> | 側欄、補充資訊,與主要內容相關但非核心 |
| <footer> | 頁面或區塊的底部,版權、連結等 |
| <button> | 可點擊的操作按鈕,絕對不要用 div 代替 |
| <a href> | 連結,絕對不要用 div onclick 代替 |
| <h1>~<h6> | 標題層級,結構要合理(不跳級) |
| <label> | 表單欄位的說明文字,必須與 input 關聯 |
| <figure> / <figcaption> | 圖表與說明文字的語義組合 |
最常見的錯誤:用 <div onClick> 模擬按鈕,或用 <div class="link"> 模擬連結。這些元素本身不具備鍵盤可訪問性(無法用 Tab 聚焦,無法用 Enter 觸發),也不會被螢幕閱讀器識別為互動元素。永遠用 <button> 和 <a href>。
Section 3:ARIA — 讓螢幕閱讀器理解你的 UI
ARIA(Accessible Rich Internet Applications)是一組 HTML 屬性,讓螢幕閱讀器理解原生 HTML 無法表達的複雜 UI 元件,例如自訂的下拉選單、Modal、Tab 切換等。ARIA 分為三大類別:
role
告訴螢幕閱讀器「這是什麼」
role="dialog"aria-* 屬性
描述「狀態、關係、說明」
aria-expanded="true"aria-live
動態更新時自動通知
aria-live="polite"1. role — 告訴螢幕閱讀器「這是什麼」
2. aria-* 屬性 — 描述狀態與關聯
3. aria-live — 動態更新通知
ARIA 第一原則
能用原生 HTML 就不要用 ARIA。 <button> 比 <div role="button"> 更好,因為原生元素已內建鍵盤支援、焦點管理等行為。ARIA 只用於原生 HTML 無法表達的複雜互動模式。
Section 4:鍵盤導航 — Tab 鍵必須能用
大多數鍵盤用戶和螢幕閱讀器用戶使用 Tab 鍵在頁面元素間移動,用 Enter 或 Space 觸發操作。原生的 <button> 和 <a href> 自動支援這些行為,但自訂元件需要額外處理。
自訂按鈕的鍵盤支援
焦點管理 — Modal 的正確實作
Modal 開啟時,焦點必須移到 Modal 內部;關閉時,焦點必須回到觸發按鈕。同時需要實作「焦點陷阱」,讓 Tab 鍵在 Modal 內循環,不允許焦點跑到背景的元素。
tabIndex 的正確使用
tabIndex={0}→ 加入 Tab 順序(依 DOM 順序)tabIndex={-1}→ 移除 Tab 焦點(但可用程式 focus)tabIndex={1}以上 → 不推薦,會破壞自然順序
focus ring 樣式
不要用 outline: none 消除焦點框!如果覺得預設樣式醜,用 Tailwind 的 focus:ring-2 focus:ring-blue-500 自訂更好看的焦點指示器。
Section 5:色彩對比與視覺設計
WCAG 2.1 規定了最低色彩對比度標準,確保視力較弱的用戶能看清文字。對比度的計算基於相對亮度(Relative Luminance),比值越高越容易閱讀。
4.5:1
一般文字
低於 18px 或非粗體
3:1
大文字
18px+ 或 14px+ 粗體
3:1
UI 元件
按鈕邊框、圖示、輸入框
對比度範例
Tailwind CSS 色彩對比速查
text-gray-300這段文字很難看到
1.9:1text-gray-400副標題文字樣本
2.9:1text-gray-500說明文字樣本文字
3.9:1text-gray-600說明文字樣本文字
5.9:1text-gray-700主要文字樣本文字
7.3:1text-blue-600連結文字樣本文字
4.5:1推薦工具
🔧
Chrome DevTools
Accessibility 面板,點選元素直接查看對比度
🪓
axe DevTools
瀏覽器擴充,一鍵掃描整頁 a11y 問題
💡
Lighthouse
Chrome 內建,a11y 評分報告(0-100 分)
Section 6:React 中的 a11y 最佳實踐
把前面所學整合到實際的 React 元件中,涵蓋圖片、表單、載入狀態、Skip Navigation 等常見場景的完整無障礙實作。
1. 圖片 alt 屬性
2. 無障礙表單完整實作
3. Skip Navigation — 讓鍵盤用戶跳過導覽
React 的 a11y 檢查工具
eslint-plugin-jsx-a11y
在開發時即時警告常見的無障礙問題,例如缺少 alt、互動元素缺少鍵盤支援等
npm install eslint-plugin-jsx-a11y@axe-core/react
在開發模式下自動掃描並在 console 顯示 a11y 問題,零配置
npm install @axe-core/react