跳到主要內容區
Accessibility Tree:細心的栽種打造無障礙頁面
開發入門

Accessibility Tree:細心的栽種打造無障礙頁面

應用程式、可訪問 API 與輔助科技的三角關係

更新日期:2023/07/06

發布日期:2023/06/18

作者:Woody

本文主要根據 Ben Myers 在其部落格上所發表的文章「The Accessibility Tree」一文進行翻譯和編修。由於某些段落的解釋較為簡略,我們在原作者的授權下進行了補充。

身障者會透過各種輔助科技來使用你的網頁。例如:螢幕閱讀器、放大鏡、眼動追蹤、語音指令等等。這些輔助科技都有一個共同的需求:它們都需要能夠存取(access)你網頁的內容。網頁內容從瀏覽器到輔助科技的流程並不常被談論,但這是讓許多身障使用者能夠訪問網際網路的重要環節。

在各方進行了大量的實驗和創新後才達成我們現在所見的成果——Accessibility Tree。這棵樹塑造了身障使用者對你網頁的理解與互動方式,同時這可能是造成無障礙與否的關鍵。作為網頁開發人員,我們的責任就是了解我們編寫的程式碼如何影響這個樹形結構。

那麼,讓我們踏上旅程穿越瀏覽器內部、作業系統和輔助科技。我們的第一站:從早期的螢幕閱讀器中學到的關於資訊流的重要教訓。

螢幕閱讀器的過去——螢幕外模型

最早期的螢幕閱讀器是為純文字的 DOS 作業系統而設計的,它們非常直接且簡單。在 DOS 作業系統中,所有資訊皆是以文字呈現,而這些文字都會在設備的螢幕緩衝區中,因此螢幕閱讀器只需要將緩衝區的內容發送到語音合成硬體中,就完成它的任務了。

然而,進入圖形使用者介面後,對於螢幕閱讀器要解析資訊變得棘手困難,因為 GUI 沒有既有的線性文字表示形式。像柏克萊系統 outSPOKEN 的早期螢幕閱讀器是透過設法攔截發送到設備圖形引擎的低級圖形指令並嘗試解釋這些指令 [1],例如:「這個帶有一些文字的矩形可能是一個按鈕」、「那邊的文字被突出顯示,所以它可能被選中了」……來解決這個問題。這些關於螢幕上內容的特定假設被儲存在螢幕閱讀器內部的資料庫中,稱為螢幕外模型。

outSPOKEN 選單。outSPOKEN 是第一個使用螢幕外模型的螢幕閱讀器。截圖由 Macintosh 存儲庫提供。
outSPOKEN 是第一個使用螢幕外模型的螢幕閱讀器。截圖由 Macintosh 存儲庫提供。

螢幕外模型存在許多問題。考慮到介面元素的對齊和放置是棘手的,而計算錯誤可能會像滾雪球般導致更大的錯誤。即使已經為你想要的 UI 元素實做了相對應的演算法,螢幕外模型所依賴的啟發式演算法仍可能是很脆弱不可靠的。[2]

猜測圖形指令的含義顯然是困難的,此外類似螢幕外模型的方法是否適用於網頁呢?螢幕閱讀器是否可以解析 HTML 或遍歷 DOM,並將頁面內容插入模型中呢?JAWS 這款螢幕閱讀器嚐試了實做了解析 HTML/DOM 並插入螢幕外模型這樣的方法,但這種方法仍存在許多問題。

首先,螢幕閱讀器和其他輔助科技通常都力求具有通用性,無論使用者執行哪個應用程式,他都應該要可以正常運作,但由於這種方法包含了大量的網頁解析邏輯而防礙了通用性。此外,當引入新的 HTML 元素時,它無法適應使用者需求。例如,當網站開始使用 HTML5 的新標籤(如 <header><footer>)時,JAWS 會忽略這些標籤內容,直到進行(昂貴的)更新才能解決這個問題。[3]

我們從螢幕外模型中學到了什麼?建立自己的網頁或應用程式的螢幕外模型的輔助科技容易出錯,並容易受到新的、不熟悉的元素和控制項影響。上述問題是這個方法所面臨的更大問題的症狀:當我們試圖逆向工程意義時,我們最終是在逆流而上,與資訊的流動背道而馳。讓我們回到源頭。我們應該讓應用程式直接告訴輔助科技它們所傳達的確切資訊,而不是讓輔助科技猜測螢幕內容。

可訪問 API 和基礎結構

如果你想要讓瀏覽器這樣的應用程式能夠向輔助科技開放資訊,你需要它們說相同的語言。因為沒有開發者會願意必需將他們的應用程式內容分別公開給每個螢幕閱讀器、語音識別軟體、眼動儀和其他輔助科技,我們需要輔助科技共用一個通用語言。這樣,那些開發瀏覽器或其他應用程式的人只需要公開它們的內容一次,任何輔助科技都可以使用它。

這種通用語言是由使用者的作業系統提供的。具體來說,作業系統有介面——可訪問 API,它們協助在程式和輔助科技之間進行翻譯。這些可訪問 API 有很棒的名字,如 Microsoft Active Accessibility、IAccessible2 和 macOS 可訪問性協議。

這些可訪問 API 如何幫助?它們為程式提供了描述其內容所需的基礎結構,並且它們作為程式和輔助科技之間的便捷中間人。

基礎結構——可訪問物件

可訪問 API 提供了應用程式描述其內容的基礎結構,這個基礎結構是稱為可訪問物件(accessible objects)的資料結構。可訪問物件具有許多屬性來描述 UI 元素的功能,這些屬性中不會描述任何視覺呈現或美學資訊。

一個這類基礎結構的例子是核取方塊物件:

{
	"name": "show tips on startup",
	"checked": true,
	"focusable": true,
	"focused": false
}

一個橘色的樂高積木上標有 Checkbox 物件的屬性。 name 是 “Show tips on startup” , checked 為 true , focusable 為 true , focused 為 false 。

另一個例子是按鈕物件:

{
	"name": "submit",
	"pressed": false,
	"focusable": true,
	"focused": true
}

一個綠色的樂高積木上標有 Button 物件的屬性。 name 是 “Submit” , pressed 為 false , focusable 為 true , focused 為 true 。

這個基礎結構使得所有應用程式都能以相似的方式描述自己。因此,就輔助科技而言,不管核取方塊出現在微軟 Word 對話框或網頁表單中,它都是一個核取方塊。(透過這種中間人的機制,輔助科技便不需要關心底層的 UI widget 是用什麼技術創建)

一個彈出視窗,其中有一個未勾選的「 Show tips at startup 」核取方塊和一個 OK 按鈕。另外還顯示了一個已勾選的「 Unsubscribe 」按鈕和一個 Submit 按鈕的網頁表單。箭頭連接了這兩個核取方塊到一個橘色的樂高積木上,並連接了這兩個按鈕到一個綠色的樂高積木上。

順帶一提,這個基礎結構包含有關 UI 元素的三種資訊:

  1. 角色:這是什麼類型的元素?是文字、按鈕、核取方塊還是其他什麼?這個資訊很重要,因為它為該元素在此處所做的事情、如何與該元素互動以及如果與該元素互動會發生什麼提供了期望。

  2. 名稱:該元素的標籤或標識符,稱為可訪問名稱。按鈕通常使用其文字內容作為名稱,因此 <button>Submit</button> 的名稱是 “Submit”。HTML 表單欄位通常從相關聯的 <label> 元素中獲得其名稱。螢幕閱讀器使用名稱來讀顯元素,語音識別使用者可以在其語音命令中使用名稱來定位特定元素。

  3. 狀態和其他屬性:元素的其他功能方面,這些方面對使用者或輔助科技很重要。此核取方塊是勾選還是未勾選?這個可展開部分當前是否隱藏?點擊此按鈕將打開下拉選單嗎?這些屬性往往比元素的角色或名稱更容易受到更改。

你可以在幾乎任何螢幕閱讀器讀顯中看到這三點:

VoiceOver 讀出 ’checked, Unsubscribe, checkbox’

中間人 — 可訪問 API

應用程式將所有內容透過這些基礎結構組合成輔助科技友好的表示形式。這種表示形式即是 Accessibility Tree。然後,應用程式將這棵 Accessibility Tree 發送到作業系統的可訪問 API。輔助科技定期輪詢可訪問 API,以獲取資訊,例如啟用的視窗、程式內容和當前聚焦的元素。

而後輔助科技可以以不同的方式使用這些資訊:

  • 螢幕閱讀器使用這些資訊來決定要讀顯什麼,或啟用快捷鍵,使使用者可以跳躍到相同類型的不同元素之上。
  • 語音識別軟體使用此資訊來確定使用者可以使用語音命令瞄準哪些元素以及如何瞄準。
  • 螢幕放大鏡使用此資訊來判斷使用者的遊標位置,以防需要將焦點放在其他地方。

此外,這種中間人關係是雙向的。可訪問 API 使輔助科技能夠與應用程式互動,為使用者提供更多靈活性。例如,眼動跟蹤技術可以將使用者凝視元素的注視視為單擊。然後,眼動跟蹤器可以將該事件通過可訪問 API 發送回來,以便瀏覽器將其視為滑鼠點擊。

將所有這些部分組合在一起,從應用程式到輔助科技的資訊流如下:

  1. 作業系統為每種 UI 元素提供可訪問物件。
  2. 應用程式使用這些物件作為基礎結構來組建 Accessibility Tree。
  3. 應用程式將此 Accessibility Tree 發送到作業系統的可訪問 API。
  4. 輔助科技定期輪詢可訪問 API 以獲取更新,接收應用程式的內容。
  5. 輔助科技向使用者公開此資訊。
  6. 輔助科技接收來自使用者的指令,例如特殊熱鍵、語音指令、開關翻轉或使用者凝視元素的注視。
  7. 輔助科技將這些指令透過可訪問 API 發送,然後轉換為與應用程式的互動。
  8. 當應用程式變化時,它向可訪問 API 提供新的 Accessibility Tree,週期重新開始。

或者,更簡短的版本:

圖示應用程式與輔助科技之間的關係,兩者中間透過可訪問 API ,進行事件、 Accessibility Tree 的溝通互動。

從 DOM 到 Accessibility Tree

我們已經相當深入地討論作業系統的內部了。現在,讓我們回到網頁。此時,我們可以想像,在背後,你的瀏覽器正在將你頁面的 HTML 元素轉換為 Accessibility Tree。當頁面更新時,它的 Accessibility Tree 也會相應更新。[4]

瀏覽器是怎麼知道要如何將 HTML 元素轉換為怎樣的 Accessibility Tree 結構呢?就像 web 中的所有事情一樣,都有個標準。為此,W3C 的 Web Accessibility Initiative 發布了「Core Accessibility API Mappings」,簡稱 Core-AAM。

Core-AAM 提供了瀏覽器在何時應選擇何種可訪問物件的指引,此外,它還指引如何計算這些可訪問物件的屬性,例如它們的名稱,以及如何管理狀態變更或鍵盤導航。

DOM 節點與 Accessibility Tree 節點之間的關係並不是一對一的。有些節點可能會被扁平化,例如只用於樣式的 <div><span>。其他元素,例如 <video> 元素,可能會被展開為 Accessibility Tree 的多個節點。這是因為影片播放器很複雜,需要呈現為多個控制項,例如播放/暫停按鈕、進度條和全螢幕按鈕。

瀏覽器允許你在其開發人員工具中查看 Accessibility Tree。現在試試看!如果你使用 Chrome,請以右鍵點擊頁面元素,然後點擊「檢查」。在打開的面板中,有如「樣式」和「計算」的標籤,請點擊「可訪問性」標籤。這可能是隱藏的。恭喜!你現在可以在 Accessibility Tree 中看到該元素!如果你使用其他瀏覽器,可以按照 Firefox 的「可訪問性檢查器」說明或 Microsoft Edge 的說明進行操作。

在不同的網站上四處逛逛,看看可以找到哪些類型的節點以及它們擁有哪些屬性。

使用 Chrome 開發人員工具查看的 Facebook 首頁的 Accessibility Tree 中, Facebook 登錄頁面上的文字框具有「可聚焦」、「可編輯」和「多行」等屬性。

但是為什麼我們要關心 Accessibility Tree 呢?

對於網頁開發人員來說,瞭解從瀏覽器到輔助科技的網頁內容流動方式,改變了我對我所工作的網頁應用程式的看法。我認為這種流動方式對網頁開發人員有三個關鍵影響:

  1. 它解釋了不同平臺上不同輔助科技之間的差異。
  2. 瀏覽器可以使用 Accessibility Tree 來優化頁面向輔助科技呈現的方式。
  3. 網頁開發人員有責任成為 Accessibility Tree 的良好管理者。

解釋差異

我們知道,在網頁內容流向輔助科技的過程中,有三個關鍵的參與者:瀏覽器、作業系統的可訪問 API 和輔助科技本身。這給了我們三個可能的差異點:

  • 作業系統的可訪問 API 可能提供不同的可訪問物件。
  • 瀏覽器可能以不同的方式組合可訪問物件而生成不同的 Accessibility Tree 。
  • 輔助科技可能以不同的方式解釋這些可訪問物件。

老實說,這些差異在大多數時候都是微小的。然而,在特定瀏覽器和輔助科技的組合下而導致的無障礙問題仍相當普遍,因此您仍應在許多不同的組合上測試您的網站。

瀏覽器優化

當建構 Accessibility Tree 時,許多瀏覽器採用啟發式演算法來改善使用者體驗。例如,許多開發人員使用 CSS 規則 display: none; 或 visibility: hidden; 從頁面上移除內容。然而,由於內容仍在 HTML 中,因此使用輔助科技的使用者仍能夠訪問,這可能會產生不良後果。瀏覽器會將這些 CSS 規則用作旗標,指示它們也應該從輔助功能樹中刪除這些元素。這就是為什麼我們必須使用其他技巧來創建僅供螢幕閱讀器使用的文字。

此外,瀏覽器使用一些技巧來保護使用者免受開發人員不良習慣的影響。例如,為了解決排版表格可能導致的問題, Google Chrome [5] 和 Mozilla Firefox [6] 會猜測 <table> 元素是用於排版還是用於表格資料,並相應地調整 Accessibility Tree 結構。

Accessibility Tree 管理

瞭解 Accessibility Tree 的重要性及其對使用者體驗的影響,應該清楚一件事:為了建立優良的 Web 應用程式,我們必須用心的哉種這顆應用程式 Accessibility Tree 。畢竟,許多輔助科技使用者只能通過 Accessibility Tree 來導航和與我們的網頁進行互動。如果我們的樹木腐爛,這些使用者實際上無法做任何事情使我們的頁面可用。

幸運的是,我們有兩種工具可管理 Accessibility Tree :語義標記和 ARIA 。當我們使用語義標記時,我們使瀏覽器更容易確定最適合的可訪問物件。例如,當我們編寫 <input type= “checkbox” /> 時,瀏覽器知道它可以將一個包含所有相關屬性的核取方塊物件放入 Accessibility Tree 中。瀏覽器可以相信這是 UI 元素的準確表示。對於按鈕和任何其他你可能想要在頁面上使用的 UI 元素,情況也是如此。

語義標記將適用於我們大部分的需求,但有時我們需要對應用程式的 Accessibility Tree 進行微調。這就是 ARIA 的作用!在後續的文章中,我們也將會探討到 ARIA 的目的 — — 修改元素在 Accessibility Tree 中的表示。

結語

幾十年來,在構建螢幕閱讀器和各種其他輔助科技方面的反復嘗試和錯誤教會了我們一個重要的教訓:當資訊直接流向輔助科技而不是逆向工程時,他能夠更可靠的工作。此外,流覽器透過大量的工作來確保我們的頁面與輔助科技良好地配合。然而,如果開發人員的工作不到位,它們將無法很好地發揮作用。

  1. Rich Schwerdtfeger, BYTE, Making the GUI Talk
  2. Léonie Watson and Chaals McCathie Nevile, Smashing Magazine, Accessibility APIs: A Key To Web Accessibility
  3. Marco Zehe, Why accessibility APIs matter
  4. Steve Faulkner, The Paciello Group, The Browser Accessibility Tree
  5. Chromium source code
  6. Firefox source code
本文作者

本文作者

Woody

熱愛學習與開發程式的軟體工程師,對知識充滿好奇心,喜歡與人的互相分享。歡迎來一起協作開發各種 accessibility 專案。