四條原則
無障礙在後台系統常被當成「以後再說」。但後台系統的使用者是每天用 8 小時的人—— 他們最需要鍵盤操作、最容易累、也最可能有需要輔具的同事。
1. 觸控目標 ≥ 44px(粗指標裝置)
@media (pointer: coarse) {
.tap-target { min-height: 44px; min-width: 44px; }
.tap-target-y { min-height: 44px; }
}
只在粗指標裝置生效:手機平板放大,桌機維持精簡尺寸。 一律 44px 會讓桌機的資料密度掉一半,那是另一種可用性問題。
tap-target-y 只放大高度:用在分頁膠囊、標籤片這類「寬度由內容決定」的元素。
2. 鍵盤要能走完全部流程
| 規則 | 說明 |
|---|---|
| Roving tabindex | 一組選項只佔一個 Tab 停留點,組內用方向鍵移動 |
| Esc 一律可退出 | 展開的編輯、浮層、導覽都要吃 Esc |
| focus-visible | 聚焦環只在鍵盤操作時出現,滑鼠點擊不顯示 |
| 焦點不能消失 | 元素被移除時要把焦點交還給合理的位置 |
四個選項的分段選擇=1 個 Tab 停留點。
不要讓四個選項各佔一個停留點。鍵盤使用者要按四次 Tab 才能離開一個欄位, 一張 30 欄的表單就是幾百次。
3. 對比:WCAG AA,淺深各驗一次
- 一般文字 4.5:1、大字(18px+ 或 14px 粗體)3:1
- UI 元件邊界 3:1
- 深色模式要分開驗——低飽和色在深色背景上很容易掉到 3:1 以下
- 驗的時候要用真正的頁面背景,不是色票研究時的比較背景
4. 顏色不是唯一線索
| 元件 | 第二條線索 |
|---|---|
| 狀態徽章 | 文字 |
| 變異顯示 | ▲▼ 箭頭 + 文字 |
| 選中狀態 | ✓ 打勾 |
| 提示框 | 固定圖示 |
| 負數金額 | 會計括號 ($2,000) |
| 鎖定欄位 | 鎖頭圖示 |
驗收方法:把畫面用灰階印出來。語意消失了就是還沒做完。
額外:鎖定的元素仍要可聚焦
<div role="group" tabIndex={0} aria-disabled aria-label="信用額度,$1,500,000(已鎖定:此筆已結案)">
disabled 的原生元素無法被聚焦,螢幕報讀器使用者跳過它時完全不知道那裡有東西、
更不知道為什麼不能改。用 aria-disabled + tabIndex={0} + 把原因寫進 aria-label。
額外:圖形化內容的文字等價
只要是用 SVG 畫出來、而且承載了資訊的東西——圖表、流程示意、進度環、 狀態分布圖——都適用這一節。它們的共同點是:資訊在圖形裡,而圖形對螢幕報讀器不透明。
role="img" 不是中性標記
很多人把 role="img" 當成「告訴輔助技術這是一張圖」的無害註記。它不是。它同時做兩件事:
1. 把這個節點當成一張圖
2. 讓它的子樹對輔助技術隱藏 ← 這件事很少被提到
第二件事的後果很具體:圖裡用 <text> 畫出來的類別名稱、數值、軸標籤,
螢幕報讀器一個都讀不到。
所以掛上 role="img" 等於做出一個承諾:我會用文字補回被隱藏的資訊。
沒補的話,這段內容對報讀器使用者是完全消失——
比不寫 role 更糟,因為不寫的話那些 <text> 至少還有機會被讀到。
這是 WCAG 1.1.1(非文字內容),Level A。
掛 role="img" 就同時給 aria-label:
一句話說出這張圖在講什麼、範圍多大、最值得注意的是什麼
(「各單位數量長條圖,共 6 個單位,最高為甲單位 1,240」)。
不要只寫 aria-label="圖表"。
那句話的資訊量等於沒有,而且它會讓這一項在稽核清單上看起來像是做完了。
文字等價用表格,不要去做 SVG 焦點管理
摘要說得出趨勢,說不出精確數值。精確數值要另外給——而給法有兩種:
| 做法 | 評估 |
|---|---|
| 讓 SVG 內的資料點可以逐個聚焦、逐個播報 | 不建議。SVG 內的焦點行為與無障礙樹支援,在各瀏覽器 × 各報讀器之間極度不一致,投入大、結果不可預期,而且做完仍然不如表格好用 |
附一份 sr-only 的 <table>(<caption> + scope) | 建議。表格語意是普世的,報讀器有專門的表格瀏覽指令(跳欄、跳列、讀表頭),使用者已經會用了 |
換句話說:不要為了無障礙去發明一種新的瀏覽方式,去用已經存在而且大家都會的那一種。
同一份資料的表格出口,順便也解決鍵盤使用者與 拿到列印版的人的問題——他們同樣拿不到懸停提示裡的數值。
不要讓任何一個數字只存在於圖裡。 懸停提示對鍵盤、觸控、報讀器三種使用情境同時不可靠, 它是加分項,不能是唯一出口。
數值已經在旁邊時,圖形要 aria-hidden
有些圖的數值本來就是可見文字:橫向堆疊條旁邊的列標籤與合計、 子彈圖的實際值與目標值、以顏色輔助的資料表。
這時再加一份文字等價,報讀器會把同一份資料唸兩次—— 而重複播報的傷害比想像中大:使用者第二次聽到相同數字時, 要先花力氣確認「這是新的一筆,還是剛才那筆」。
| 情況 | 做法 |
|---|---|
| 資訊只在圖形裡 | role="img" + 摘要 + sr-only 表格 |
| 數值已在鄰近可見文字 | 圖形標 aria-hidden,讓可見文字負責 |
| 本體就是表格、顏色只是輔助 | 不加圖形語意,改把表格語意補正確(caption/scope/列標頭用 <th scope="row">) |
判準只有一句:同一筆資料,在無障礙樹裡只能出現一次。
把圖形標 aria-hidden 之前,先確認可見文字真的涵蓋了全部資訊。
只列了合計而分段明細只在圖裡的話,明細仍然要有出口。
不要用 aria-hidden 當偷懶的出口。
它的意思是「這裡沒有新資訊」,不是「這裡的資訊我不想處理」。
已知限制要明講
如果懸停提示與點擊鑽取目前只有滑鼠拿得到(資料點沒有 tabIndex / onKeyDown),
那是 WCAG 2.1.1(鍵盤),Level A——要寫進文件當成已知限制,
不要讓使用它的人以為那些互動是鍵盤可用的。
建議的解法同樣是讓那份表格兼任鍵盤介面(表格列可觸發同一個鑽取動作), 而不是回頭去做 SVG 的焦點管理。理由同上。