Angular 無(wú)障礙性

2022-07-13 10:34 更新

Angular 中的無(wú)障礙功能

Web 會(huì)被各種各樣的人使用,包括有視覺或運(yùn)動(dòng)障礙的人。有多種輔助技術(shù)能使這些人更輕松地和基于 Web 的軟件應(yīng)用進(jìn)行交互。另外,將應(yīng)用設(shè)計(jì)得更易于訪問通常也能改善所有用戶的體驗(yàn)。

關(guān)于如何設(shè)計(jì)無(wú)障礙應(yīng)用的問題和技術(shù)的深入介紹,參閱 Google 網(wǎng)絡(luò)基礎(chǔ)知識(shí)無(wú)障礙功能部分。

本頁(yè)討論了設(shè)計(jì) Angular 應(yīng)用的最佳實(shí)踐,這些實(shí)踐對(duì)所有用戶(包括依賴輔助技術(shù)的用戶)都適用。

本頁(yè)中所講的范例程序,參閱現(xiàn)場(chǎng)演練 / 下載范例

無(wú)障礙屬性(Attribute)

建立無(wú)障礙的 Web 體驗(yàn)通常會(huì)涉及設(shè)置 ARIA 屬性(Attribute) 以提供可能會(huì)丟失的語(yǔ)義。使用 Attribute 綁定模板語(yǔ)法來(lái)控制與無(wú)障礙性相關(guān)的屬性(Attribute)值。

在 Angular 中綁定 ARIA 屬性(Attribute)時(shí),必須使用 ?attr.? 前綴,因?yàn)?nbsp;ARIA 規(guī)范針對(duì)的是 HTML 屬性(Attribute),而不是 DOM 元素的屬性(Property)。

<!-- Use attr. when binding to an ARIA attribute -->
<button [attr.aria-label]="myActionLabel">…</button>
注意
此語(yǔ)法僅對(duì)于屬性(Attribute)綁定是必需的。靜態(tài) ARIA 屬性(Attribute)不需要額外的語(yǔ)法。
<!-- Static ARIA attributes require no extra syntax -->
<button aria-label="Save document">…</button>

按照約定,HTML 屬性(Attribute)使用小寫名稱(?tabindex?),而 Property 使用 camelCase 名稱(?tabIndex?)。

Angular UI 組件

由 Angular 團(tuán)隊(duì)維護(hù)的 Angular Material 庫(kù)是旨在提供完全無(wú)障礙的一組可復(fù)用 UI 組件。組件開發(fā)工具包(CDK)中包括 a11y 軟件包,該軟件包提供了支持無(wú)障礙領(lǐng)域的各種工具。比如:

  • ?LiveAnnouncer ?用于使用 ?aria-live? 區(qū)域向屏幕閱讀器用戶朗讀消息。關(guān)于 aria-live 領(lǐng)域的更多信息,參閱 W3C 文檔。
  • ?cdkTrapFocus ?指令能將 Tab 鍵焦點(diǎn)捕獲在元素內(nèi)。使用它可為必須限制焦點(diǎn)的模態(tài)對(duì)話框之類的組件創(chuàng)建無(wú)障礙體驗(yàn)。

關(guān)于這些工具和其它工具的完整詳細(xì)信息,參閱 Angular CDK 無(wú)障礙功能概述。

增強(qiáng)原生元素

原生 HTML 元素捕獲了許多對(duì)無(wú)障礙性很重要的標(biāo)準(zhǔn)交互模式。在制作 Angular 組件時(shí),應(yīng)盡可能直接復(fù)用這些原生元素,而不是重新實(shí)現(xiàn)已獲良好支持的行為。

比如,你可以創(chuàng)建一個(gè)組件,它使用屬性(Attribute)選擇器指向原生 ?<button>? 元素,而不是為各種新按鈕創(chuàng)建自定義元素。通常這適用于 ?<button>? 和 ?<a>?,但也可以用于許多其它類型的元素。

你可以在 Angular Material 中看到此模式的范例:MatButton,MatTabNav,MatTable。

將容器用于原生元素

有時(shí)要使用的原生元素需要一個(gè)容器元素。比如,原生 ?<input>? 元素不能有子元素,因此任何自定義的文本輸入組件都需要用其它元素來(lái)包裝 ?<input>?。盡管你可能只在自定義組件的模板中包含 ?<input>?,但這將使該組件的用戶無(wú)法為 ?input ?元素設(shè)置任意 Property 和 Attribute。相反,你可以創(chuàng)建一個(gè)使用內(nèi)容投影的容器組件,以將原生控件包含在組件的 API 中。

你可以把 MatFormField 作為該模式的例子。

案例研究:構(gòu)建自定義進(jìn)度條

以下范例顯示如何通過使用宿主(host)綁定來(lái)控制與無(wú)障礙性相關(guān)的屬性(Attribute),來(lái)把進(jìn)度條無(wú)障礙化。

  • 該組件使用標(biāo)準(zhǔn)的 HTML 屬性(Attribute)?role ?和 ARIA 屬性(Attribute)來(lái)定義要啟用無(wú)障礙支持的元素。ARIA 屬性(Attribute)?aria-valuenow? 綁定到用戶的輸入。
  • import { Component, Input } from '@angular/core';
    
    /**
     * Example progressbar component.
     */
    @Component({
      selector: 'app-example-progressbar',
      template: '<div class="bar" [style.width.%]="value"></div>',
      styleUrls: ['./progress-bar.component.css'],
      host: {
        // Sets the role for this component to "progressbar"
        role: 'progressbar',
    
        // Sets the minimum and maximum values for the progressbar role.
        'aria-valuemin': '0',
        'aria-valuemax': '100',
    
        // Binding that updates the current value of the progressbar.
        '[attr.aria-valuenow]': 'value',
      }
    })
    export class ExampleProgressbarComponent  {
      /** Current value of the progressbar. */
      @Input() value = 0;
    }
  • 在模板中,?aria-label? 屬性(Attribute)可以確保屏幕閱讀器能訪問該控件。
  • <label>
      Enter an example progress value
      <input type="number" min="0" max="100"
          [value]="progress" (input)="setProgress($event)">
    </label>
    
    <!-- The user of the progressbar sets an aria-label to communicate what the progress means. -->
    <app-example-progressbar [value]="progress" aria-label="Example of a progress bar">
    </app-example-progressbar>

路由

導(dǎo)航后的焦點(diǎn)管理

在設(shè)計(jì)無(wú)障礙性時(shí),在 UI 中跟蹤和控制焦點(diǎn)是很重要的考慮因素。使用 Angular 路由時(shí),你需要確定頁(yè)面焦點(diǎn)在導(dǎo)航上的位置。

為了避免僅僅依靠視覺提示,你需要確保路由代碼會(huì)在頁(yè)面導(dǎo)航之后更新焦點(diǎn)。使用 ?Router ?服務(wù)中的 ?NavigationEnd ?事件可以知道何時(shí)該更新焦點(diǎn)。

以下范例顯示了導(dǎo)航后如何在 DOM 中查找并把焦點(diǎn)移動(dòng)到主體內(nèi)容的頭部。

router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe(() => {
  const mainHeader = document.querySelector('#main-content-header')
  if (mainHeader) {
    mainHeader.focus();
  }
});

在實(shí)際的應(yīng)用程序中,哪些元素獲得焦點(diǎn)將取決于該應(yīng)用特有的結(jié)構(gòu)和布局。獲得焦點(diǎn)的元素應(yīng)使用戶能夠立即移動(dòng)到剛剛進(jìn)入視野的主要內(nèi)容。你應(yīng)該避免當(dāng)路由變化后焦點(diǎn)重新回到 ?body ?元素的情況。

活動(dòng)鏈接標(biāo)識(shí)

用在活躍 ?RouterLink ?元素上的 CSS 類(一般通過 ?RouterLinkActive ?來(lái)指定)提供了有關(guān)哪個(gè)鏈接正處于活躍狀態(tài)的視覺指示。此類指示不適用于盲人或視障用戶,為了提供此類信息,還要將 ?aria-current? 屬性應(yīng)用于此元素(有關(guān)更多信息,參閱MDN aria-current)。

?RouterLinkActive ?指令提供了 ?ariaCurrentWhenActive ?輸入屬性,該輸入屬性會(huì)在鏈接變?yōu)榛钴S狀態(tài)時(shí)將 ?aria-current? 設(shè)置為指定的值。

以下示例展示了如何將 ?active-page? 類應(yīng)用于活躍鏈接,以及如何在它們處于活躍狀態(tài)時(shí)將它們的 ?aria-current? 屬性設(shè)置為 ?"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>


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)