網路的使用者形形色色,其中也包括視覺或行動方面有障礙的人。 市面上有各種輔助技術,能讓這些族群更容易與以網路為基礎的軟體應用程式互動。 此外,把應用程式設計得更容易使用,通常也能改善所有使用者的整體體驗。
若想深入了解設計無障礙應用程式的議題與技巧,請參閱 Google 在 web.dev 上的 Learn Accessibility 課程。
本頁說明設計 Angular 應用程式的最佳實務,讓所有使用者(包括仰賴輔助技術的人)都能順暢使用。
無障礙屬性
要打造無障礙的網路體驗,往往需要設定 Accessible Rich Internet Applications(ARIA)屬性,在原本缺少語意的地方補上語意。 你可以用屬性繫結範本語法,控制與無障礙相關的屬性值。
ARIA 屬性與內容
在 Angular 中繫結 ARIA 屬性時,可以像其他 HTML 屬性一樣直接使用。
<button [aria-label]="myActionLabel">…</button>
靜態的 ARIA 屬性就和一般 HTML 屬性一樣運作。
<button aria-label="Save document">…</button>
HELPFUL: 依照慣例,HTML 屬性使用小寫名稱(tabindex),屬性(property)則使用 camelCase 名稱(tabIndex)。
有些 ARIA 模式會公開接受結構化值的 DOM API 或指令輸入(例如 Element 參考的集合)。這類情況請使用標準的屬性繫結,讓底層的關聯保持同步。
@Component({
template: `
<h2 #dialogTitle>Attention</h2>
<p #dialogDescription>Please review your answers before continuing.</p>
<section role="dialog" [ariaLabelledByElements]="[dialogTitle, dialogDescription]">
<ng-content />
</section>
`,
})
export class ReviewDialog {}
這裡的 [ariaLabelledByElements] 接受元素陣列,因此只要範本資料一變,屬性繫結就能讓元素參考隨時保持最新。
ARIA 屬性語法的摘要,請參閱繫結指南。
Angular UI 元件
由 Angular 團隊維護的 Angular Material 程式庫,是一套可重複使用的 UI 元件,目標是做到完全無障礙。
Component Development Kit(CDK) 包含 a11y 套件,提供支援各個無障礙領域的工具。
例如:
LiveAnnouncer會利用aria-live區域,為螢幕閱讀器使用者播報訊息。 更多關於 aria-live 區域 的資訊,請參閱 W3C 文件。cdkTrapFocus指令會把 Tab 鍵的焦點限制在某個元素內。 你可以用它為模式對話框之類的元件打造無障礙體驗,這類元件必須限制焦點的移動範圍。
這些工具與其他工具的完整說明,請參閱 Angular CDK 無障礙總覽。
對於需要可重複使用 WAI-ARIA 互動模式的自訂樣式元件,Angular Aria 提供無頭(headless)指令,涵蓋手風琴、組合框、清單框、選單、頁籤與工具列等模式。 這些指令會處理鍵盤互動、ARIA 屬性、焦點管理與螢幕閱讀器支援,同時讓你自行提供應用程式的 HTML 結構與樣式。
強化原生元素
原生 HTML 元素本身就具備幾個對無障礙很重要的標準互動模式。 撰寫 Angular 元件時,只要做得到,就應該直接重複使用這些原生元素,而不是重新實作已經有良好支援的行為。
例如,與其為新型態的按鈕建立自訂元素,不如建立一個使用屬性選擇器、搭配原生 <button> 元素的元件。
這最常用在 <button> 與 <a> 上,但也能用在許多其他類型的元素。
你可以在 Angular Material 裡看到這種模式的範例:
MatButton、MatTabNav 與 MatTable。
用容器包裝原生元素
有時候,要使用合適的原生元素,就需要一個容器元素。
例如,原生 <input> 元素不能有子元素,所以任何自訂文字輸入元件都需要用額外元素把 <input> 包起來。
若只是把 <input> 放進自訂元件的範本裡,元件的使用者就無法對 <input> 元素設定任意的屬性與特性。
這種情況下,應該建立一個容器元件,利用內容投影把原生控制項納入元件的 API。
你可以把 MatFormField 當作這種模式的範例。
案例研究:打造自訂進度列
下面的範例示範如何利用主機繫結(host binding)控制與無障礙相關的屬性,讓進度列變得無障礙。
- 元件定義了一個支援無障礙的元素,同時用上標準 HTML 屬性
role與 ARIA 屬性。 ARIA 屬性aria-valuenow會繫結到使用者的輸入。 - 在範本中,
aria-label屬性確保螢幕閱讀器能存取這個控制項。
路由
導航後的焦點管理
在 UI 中追蹤並控制焦點,是無障礙設計的重要考量。 使用 Angular 路由時,你應該決定頁面導航後焦點要移到哪裡。
為了避免只仰賴視覺提示,你需要確保路由程式碼在頁面導航後會更新焦點。
你可以用 Router 服務的 NavigationEnd 事件,掌握更新焦點的時機。
下面的範例示範導航後如何在 DOM 中找到主要內容的標題並把焦點移到它上面。
router.events.pipe(filter((e) => e instanceof NavigationEnd)).subscribe(() => {
const mainHeader = document.querySelector('#main-content-header');
if (mainHeader) {
mainHeader.focus();
}
});
在真實應用程式中,接收焦點的元素取決於你應用程式的具體結構與版面配置。
取得焦點的元素,應該讓使用者能立刻進入剛被路由帶進畫面的主要內容。
你應該避免路由切換後焦點回到 body 元素的情況。
使用中連結的標示
套用在作用中 RouterLink 元素上的 CSS 類別(例如 RouterLinkActive),會提供視覺提示來標示作用中的連結。
可惜的是,視覺提示對盲人或視障使用者沒有幫助。
把 aria-current 屬性套用到元素上,能協助標示作用中的連結。
更多資訊請參閱 Mozilla Developer Network(MDN)的 aria-current)。
RouterLinkActive 指令提供 ariaCurrentWhenActive 輸入,當連結變成作用中時,會把 aria-current 設為指定的值。
下面的範例示範如何把 active-page 類別套用到作用中的連結,同時在連結作用中時把它的 aria-current 屬性設為 "page":
<nav>
<a routerLink="home" routerLinkActive="active-page" ariaCurrentWhenActive="page"> Home </a>
<a routerLink="about" routerLinkActive="active-page" ariaCurrentWhenActive="page"> About </a>
<a routerLink="shop" routerLinkActive="active-page" ariaCurrentWhenActive="page"> Shop </a>
</nav>
延遲載入
使用 Angular 的 @defer 區塊延遲載入內容時,請考慮對使用輔助技術的使用者有何影響。
當延遲載入的元件完成載入時,螢幕閱讀器不一定會自動播報內容變化,使用者可能因此不知道有新內容出現。
為了確保延遲內容的變化能被正確播報,請把 @defer 區塊包在帶有適當 ARIA live 區域的元素裡。
詳細指引與範例,請參閱 defer 指南中的無障礙章節。
更多資訊
- Accessibility - Google Web Fundamentals
- ARIA specification and authoring practices
- Material Design - Accessibility
- Smashing Magazine
- Inclusive Components
- Accessibility Resources and Code Examples
- W3C - Web Accessibility Initiative
- Rob Dodson A11ycasts
- Angular ESLint 提供 lint 規則,能協助你確保程式碼符合無障礙標準。
書籍
- "A Web for Everyone: Designing Accessible User Experiences," Sarah Horton and Whitney Quesenbery
- "Inclusive Design Patterns," Heydon Pickering