Skip to main content

無障礙網站 Accessibility 做不做,究竟能差多少?

很多無障礙(accessibility, a11y)介紹文章都講正面範例,完全感受不出不做會怎樣,本文以反例示範不良的 a11y 網站會有什麼問題。

a11y 怎麼做都很難影響到行動正常的人,就算你反著做畫面都看不出來,但是如果 a11y 做的很差,對於行動不便者那就很難受了,行動不便具體來說就是肢體不方便行動或是視覺有障礙,a11y 的目的就是讓這些人能夠方便的操作和理解你的網站。你可以想像這些人已經不方便出門了,現在網站連讓他們方便瀏覽都做不到,那就有點殘酷了。

以 Hinode 為例​

舉例來說,以 Hinode 主題的文章列表頁面為例,一個簡單的小區塊就出現多個錯誤,這是一個 cards wrapper 和內部的卡片,僅僅兩個組件就有 4 (+2) 項錯誤:

<div class="row row-cols-1">
<div class="col">
<div class="card card-emphasize">
<div class="card-icon">
<svg aria-hidden="true" role="img" viewBox="0 0 16 16">...</svg>
</div>
<div class="card-body">
<a href="/docs/getting-started/" class="card-body-link stretched-link">
<p class="card-title">Getting Started</p>
<div class="card-text card-body-link">Grasp the fundamentals to get you started.</div>
</a>
</div>
</div>
</div>
</div>

這個實現有多個問題:

  1. role="img" 與 aria-hidden="true" 矛盾

    role="img" 告訴輔助技術「這是一張圖片,應該被播報」,aria-hidden="true" 告訴輔助技術「忽略這個元素」,兩者衝突。

  2. <svg> 沒有 <title> 子元素,role="img" 的語義不完整

    延續上一點如果真的要用 role="img",需要搭配 <title> 才能提供可播報的名稱,否則 role="img" 不提供 accessible name。

  3. stretched-link 把整張 card 變成可點擊區域,但 focus 可視範圍只框住文字連結本身

    stretched-link 是視覺和滑鼠行為上的擴大點擊區,鍵盤 focus ring 預設只會出現在 <a> 標籤本身(文字區域),實際可操作範圍和框選範圍不一致。

  4. 文章列表頁面應該用列表實現

    HTML 的 list 結構明確傳達「這是一組同類型項目的集合」,螢幕閱讀器會播報項目總數與目前位置(例如「清單,共 8 項,第 1 項」),讓使用者知道這是一組可瀏覽的集合,也能用 list 導航快速跳過或逐項瀏覽。

    目前的 <div class="row"> + 多個 <div class="col"> 沒有任何語義,螢幕閱讀器無法辨識這是一組集合,使用者只會逐個遇到不相關的 <div>,不知道總數、不知道自己在集合中的位置,也無法用 list 導航跳過整組內容。

  5. 文章卡片應該用 article 標籤

    article 標籤代表該內容可獨立出現也帶有完整理解語意,因為這裡包含了標題和敘述,卡片已經有獨立語意表達了,用 article 是更好的選項,不過這不是嚴重問題,是額外優化。

  6. 不考慮 prefers-reduced-motion

    前庭功能障礙用戶會開啟此設定減少動畫效果,這裡的 CSS 沒有考慮此設定。

這樣指出之後讀者應該就能清楚知道做好、做不好 a11y 的差別有多大,修正如下,這些修正完全不影響行動正常的用戶,但是對需要 a11y 的用戶就是能直接感受到的不同。

<ul class="row row-cols-1">
<li class="col">
<article class="card card-emphasize">
<div class="card-icon">
<svg aria-hidden="true" viewBox="0 0 16 16" overflow="visible">...</svg>
</div>
<div class="card-body">
<a href="/docs/getting-started/" class="card-body-link stretched-link">
<h3 class="card-title fs-lg-5 fs-6">Getting Started</h3>
<div class="card-text card-body-link">Grasp the fundamentals to get you started.</div>
</a>
</div>
</article>
</li>
</ul>

冰山一角​

這只是冰山一角,只是一個網站數十個組件裡面的其中一個,想像如果整個網站都充滿類似問題,行動不便者瀏覽網站會有多困難。筆者不是專家,但是透過這個簡單範例讀者就能知道 a11y 具體影響了哪些東西。

具體有多冰山一角呢,以卡片組件為例,卡片是整個前端最基本的東西了,只要一個框起來的區域,不管裡面塞什麼都算卡片,這麼基礎的東西寫 a11y 可以讓從業者不斷優化整理出這麼長的文章:

筆者也不是特意挑一個 star 數少、維護量能小的專案去找他的麻煩,讀者可以看 Hinode 的倉庫提交狀態,這個專案的維護強度反而是大到誇張的那種。

以 Hextra 為例​

不然再舉一個例子,以更知名 2.4k 星星數的 hextra 主題來說,同樣以列表頁面舉例,v0.13.0 的頁面也有一堆 a11y 問題:

  1. 左側導航欄:按鈕過小,規範要求 AA 等級至少要 24x24,好一點 AAA 等級要 44x44,他只有 18x18,(這小到連我是一般人都覺得不好按,實際可點面積少了 44%,也就是說比最低要求還小了快一半)
  2. 左側導航欄:鍵盤導覽會被困在裡面。第一,鍵盤導覽時會進入折疊的內容內部,就被困在一堆連結裡面出不來;第二,進入摺疊的內容後,摺疊區域也沒有自動展開,等同完全失去自己當前位置的資訊
  3. 內容區麵包屑導航:應該用列表展示才符合 APG 建議
  4. 內容區文章連結:應該用列表展示才符合 APG 建議
  5. 右側 TOC 區:用了 CSS order 讓 DOM 順序和顯示順序不同,違反 a11y 要求
  6. 右側 TOC 區:scroll to top 按鈕在隱藏時仍然會被導航工具聚焦,用戶會聚焦到看不到的內容

以 material-mkdocs 為例​

雖然 Material for Mkdocs 已經終止維護,但他仍然是世界知名、使用量非常多的文檔工具,不過經過筆者實測才發現這網站的 a11y 導覽反而是本文中最糟糕的,是差到不能再差的那種,糟糕到值得特別把他拿出來講,光是網站頂端導航欄一個組件就慘成這樣:

  1. 網站名稱被唸了六次:圖案一次,hover 的 tooltip 進去前一次,進入後一次,出來又一次;後面的文字標題一次,程式碼錯誤重複出現一個視覺隱藏版本但是輔助工具還是讀的到該版本,加起來總共六次
  2. Dark mode switcher 強制進入無法跳出,會經過三次才離開
  3. 搜尋欄位自動展開,會把搜尋欄裡面所有東西都唸過一輪才離開,需要 15 次跳轉
  4. 畫面右上方的 repo 名稱、星星數等資訊,沒有 aria-label 輔助只唸純文字,無法理解資訊

這絕對是最差的範例了,這四個內容應該各自只被唸一次,但是總共唸了 25 次,還有一個唸的內容意義不清,如果這只是個人網站那沒必要把他拿出來講,但這可是使用數量名列前茅的工具。

結尾​

透過三個反例應該更能理解行動不便用戶的感受,筆者不是鑽牛角尖挑毛病,讀者可以測試其他專案如 Docusaurus 就沒有出現上述任何一個問題,也不必是大專案才能做到,這是開發者有沒有意識的問題,像是 hugo-yore 同樣沒有上述任何一個問題。

應該將心比心想像一下行動不便者瀏覽網站時會遇到哪些困難,a11y 不必完美,但是 8020 法則至少關鍵核心應該做好優化。