打造更容易使用的 Angular 應用程式

1. 事前準備

黑色 Angular 標誌

無障礙功能是網頁開發的重要環節,可確保使用者能感知、瞭解、瀏覽及操作應用程式。事實上,每 4 位美國成人就有 1 位身心障礙,生活受到重大影響。全球約有 15% 的人口 (超過 10 億人) 患有某種形式的身心障礙,其中約有 2% 至 4% 的人面臨嚴重困難。

失能情況會影響使用網路,而常見的失能情況包括失明或視障、失聰或聽障、動作技巧受限、認知障礙及色盲,這只是部分例子。

在本課程中,a11y 是無障礙功能的簡稱。請注意,a 後面接著 11 個字元和 y

如要深入瞭解無障礙應用程式的設計問題和技術,請參閱「無障礙功能」。

建構項目

  • 運用最佳做法和內建技術,解決示範 Dumpling Shop Angular 應用程式中的常見無障礙網頁問題
  • 符合所有無障礙規範、WCAG 2.0 和 ARIA 1.2,並通過 axe 和 Lighthouse 無障礙稽核。

以粉紅色和紅色為主題的 Dumpling Time 商店網站 以紫色和綠色為主題的 Dumpling Time 商店網站

課程內容

您將瞭解 Angular 應用程式中影響使用者的八個常見無障礙問題、如何找出這些問題,以及如何修正。具體來說,這個管道應能完成以下工作:

  • 使用 Google Chrome 開發人員工具、Lighthouse 和 axe 稽核應用程式的無障礙功能
  • 使用獨一無二的網頁標題,解決單頁應用程式 (SPA) 的缺點
  • 為低視能使用者修正低色彩對比問題
  • 使用語意式 HTML,確保螢幕閱讀器能正確瀏覽網頁
  • 使用 Angular Material 並取消巢狀控制項,確保螢幕閱讀器可以存取所有控制項
  • 為螢幕閱讀器新增 ARIA 支援功能
  • 匯入及使用 Angular CDK a11y 套件
  • 使用 FocusTrap 進行自訂元件螢幕閱讀器導覽
  • 使用 CDK LiveAnnouncer 播報通知
  • 偵測使用高對比模式的使用者,並實作高對比主題

軟硬體需求

2. 做好準備

取得程式碼

本專案所需的一切內容都位於 GitHub 存放區中。如要開始使用,請複製程式碼,然後在您慣用的開發環境中開啟。

複製存放區並提供應用程式

建議使用 VSCode 或本機 IDE 完成本程式碼研究室。

  1. 開啟新的瀏覽器分頁,然後前往 https://github.com/googlecodelabs/angular-accessibility
  2. 建立存放區分支並加以複製,然後 cd angular-accessibility/ 存放區。
  3. 查看範例程式碼分支版本 git checkout get-started
  4. 在 VSCode 或慣用的 IDE 中開啟程式碼。
  5. 執行 npm install,安裝執行伺服器所需的依附元件。
  6. 執行 ng serve 即可執行伺服器。
  7. 開啟瀏覽器分頁,前往 http://localhost:4200

3. 建立基準

從哪裡開始?

您要從專為本次程式碼研究室所設計的基本餐廳應用程式開始。程式碼已簡化,僅用於說明本程式碼研究室的概念,功能不多。

以紫色和綠色為主題的 Dumpling Time 商店網站

觀看示範

如要開始使用,請逐步瞭解應用程式的三項功能:

  1. 使用導覽列查看「我們的商店」、「我們的故事」和「尋找我們」路線,並查看餃子公司的詳細資料。
  2. 變更主題即可切換淺色和深色模式。
  3. 自訂訂單的餃子餡料、數量和顏色。
  4. 選取「購買」,在管理中心記錄自訂訂單。

使用 Angular 解決常見的網頁無障礙問題

在本程式碼研究室中,您將著重於這個應用程式現有功能的無障礙程度。首先,您會找出應用程式中的無障礙功能問題,然後實作解決方案,將 🛑 變成 ✅。

如何知道要修正哪些問題?

首先,請使用手動和自動測試,找出每個範例中的無障礙功能問題。

在目前的網頁狀態下,手動測試無障礙功能是必要做法。

您可以使用工具找出無障礙問題,但沒有任何工具可以認證應用程式完全符合無障礙標準。手動測試可確保您測試各種無障礙概念,包括邏輯內容順序和功能同位。

手動測試

在本課程中,如要手動測試無障礙功能,請開啟電腦內建的螢幕閱讀器,並使用鍵盤瀏覽應用程式。詳情請參閱「語意和螢幕閱讀器」。

開啟螢幕閱讀器並瀏覽畫面,即可練習操作。

你可以使用 macOS 內建的 VoiceOver。依序點選「系統偏好設定」 >「輔助功能」 >「旁白」 >「啟用旁白」。如要切換 VoiceOver,請按住 Command 鍵,然後快速按三下 Touch ID。

在本課程中,您主要會手動測試問題,並使用自動化工具協助檢查特定可自動化的功能。

自動化測試

您也可以使用幾項開發工具,自動化稽核應用程式。這些工具可讓您檢查圖片是否有替代文字,或文字顏色的對比度。您可以將這些工具視為 Linter,它們可以辨識是否有替代文字,但您必須手動檢查內容是否合乎邏輯且有價值。

Lighthouse 和 Chrome 開發人員工具

  1. 開啟 Chrome 開發人員工具。
  2. 選取「Lighthouse」分頁標籤,然後勾選「無障礙」核取方塊。
  3. 按一下「產生報表」,執行無障礙 Lighthouse 稽核。

Lighthouse 範例分頁,其中有在 Chrome 開發人員工具分頁中產生報表的按鈕

斧頭

  1. 安裝 axe DevTools 擴充功能。你可能需要重新啟動瀏覽器,才能看到擴充功能。
  2. 開啟 Chrome 開發人員工具。
  3. 選取「axe DevTools」分頁標籤,然後選取「Scan all of my page」,執行 axe DevTools 掃描。

Linting

您可以使用 Angular ESLint 規則檢查程式碼,找出可自動化的無障礙屬性。

eslint.json 中新增下列無障礙功能適用的項目:

"@angular-eslint/template/accessibility-alt-text": 2,
"@angular-eslint/template/accessibility-elements-content": 2,
"@angular-eslint/template/accessibility-label-for": 2,
"@angular-eslint/template/no-positive-tabindex": 2,
"@angular-eslint/template/accessibility-table-scope": 2,
"@angular-eslint/template/accessibility-valid-aria": 2,
"@angular-eslint/template/click-events-have-key-events": 2,
"@angular-eslint/template/mouse-events-have-key-events": 2,
"@angular-eslint/template/no-autofocus": 2,
"@angular-eslint/template/no-distracting-elements": 2

詳情請參閱 GitHub 上的最新 ESLint 規則。

您的起點

使用新的測試方法,您可以使用 Lighthouse 和 axe 稽核,以及手動 VoiceOver,找出應用程式中的下列問題:

Chrome 開發人員工具 Lighthouse 稽核,分數為 82 分

無障礙稽核:

  • 🛑 所有網頁的網頁標題都相同
  • 🛑 元素必須有足夠的色彩對比
  • 🛑 HTML 應具有邏輯順序、名稱和角色
  • 🛑 螢幕閱讀器無法選取巢狀核取方塊
  • 🛑 螢幕閱讀器不會朗讀滑桿值
  • 🛑 螢幕閱讀器焦點位於色彩選擇器時,會退出對話方塊
  • 🛑 不會公布異動、錯誤和通知
  • 🛑 未啟用高對比模式

4. 定義獨特的網頁標題

提供簡潔獨特的網頁標題,可協助使用無障礙服務的使用者快速瞭解網頁內容和用途。頁面標題是視障使用者最重要的資訊,因為螢幕閱讀軟體會先朗讀頁面標題。

Angular 是單頁應用程式,因此大多數的轉場效果 (例如移至新頁面) 都不會重新載入頁面。直到最近,這都表示每個網頁都有相同的網頁標題,無法提供任何價值來瞭解網頁內容或用途。

在 Angular v14 中,Router 新增了內建方法,可直接定義不重複的網頁標題。這樣一來,就能以簡化的方式確保開發人員遵循網頁標題最佳做法。

完成本節後,您的應用程式將通過下列稽核:

  • 🛑 所有網頁的網頁標題都相同

你可以在留言下方找到這些步驟:TODO: #4. Define unique page titles.

找出問題

如要找出這個問題,請開啟螢幕閱讀器,然後在「我們的商店」、「我們的故事」和「尋找我們」分頁之間瀏覽,查看頁面標題:

  1. 開啟 VoiceOver。
  2. 使用分頁導覽功能瀏覽不同頁面。
  3. 確認頁面標題在 Angular 中一律為 a11y。

這是個問題,因為網頁標題必須獨一無二,使用者才能快速瞭解網頁內容,不必實際瀏覽。

Chrome 瀏覽器開啟三個分頁,頁面標題相同:「a11y in Angular」

新增有意義的網頁標題

如果頁面或檢視畫面有所變更,請妥善管理頁面標題。如要修正這個問題,請使用 Angular 內建的 Router.title 屬性,為每個網頁定義專屬標題。

  1. 為定義的三條路徑分別新增專屬標題:

src/app/app-routing.module.ts

const routes: Routes = [
  { path: 'shop', component: ShopComponent, title: 'Our Shop – a11y in Angular' },
  { path: 'about', component: AboutComponent, title: 'Our Story - a11y in Angular' },
  { path: 'locate', component: LocationComponent, title: 'Find Us - a11y in Angular' },
  { path: '',   redirectTo: '/shop', pathMatch: 'full' },
  { path: '**', component: ShopComponent },
];

這會自動匯入並使用 Router's Title Service,在導覽時管理頁面標題的變更,以符合在路徑中定義的標題屬性。您也可以使用自訂 TitleStrategy 管理更複雜的網頁標題。

驗證變更

再次開啟螢幕閱讀器,確認變更是否生效。現在頁面應該都有不重複的標題了!

Chrome 瀏覽器開啟三個分頁,分別顯示獨特的頁面標題:「Our Shop - a11y in Angular」、「Our Story - a11y in Angular」、「Find Us - a11y in Angular」

無障礙稽核:

  • 所有網頁都有獨一無二的網頁標題
  • 🛑 元素必須有足夠的色彩對比
  • 🛑 HTML 應具有邏輯順序、名稱和角色
  • 🛑 螢幕閱讀器無法選取巢狀核取方塊
  • 🛑 螢幕閱讀器不會朗讀滑桿值
  • 🛑 螢幕閱讀器焦點位於色彩選擇器時,會退出對話方塊
  • 🛑 不會公布異動、錯誤和通知
  • 🛑 未啟用高對比模式

5. 確保色彩對比度充足

您的設計可能很酷,但如果色盲等視障者無法閱讀您的內容,就不是好設計。無障礙網頁內容規範 (WCAG 2.0) 定義了一系列色彩對比度,確保內容符合無障礙設計規範。在 Angular 和網頁上,您可以定義色彩調色盤,確保元件符合這些標準,且視力不佳和色盲的使用者也能看見。

完成本節後,您的應用程式將通過下列稽核:

  • 🛑 元素必須有足夠的色彩對比

你可以在留言下方找到每個步驟:TODO: #5. Ensure adequate color contrast.

使用 Chrome 開發人員工具找出對比度過低的問題

如要找出這個問題,請使用 Chrome 開發人員工具檢查應用程式中的元素。

  1. 使用檢查工具查看選單圖示按鈕。您可以看到對比度為 1.85,遠低於 WCAG 規定

Chrome 開發人員工具檢查對比度偏低的「首頁」按鈕元素

  1. 在 Lighthouse 或 axe 的掃描中執行無障礙稽核,即可查看這些對比率問題。

Chrome 開發人員工具 Lighthouse 稽核結果顯示錯誤:「背景和前景顏色沒有足夠的對比度」

變更 Material 主題顏色

元件色彩配置是在自訂 Material Design 主題中定義。更新主題值,以符合色彩對比度指南。

更新 Material 主題,使用較深的文字顏色,提高圖示的對比度:

src/styles.scss

$light-primary: mat.define-palette(mat.$pink-palette, $default: A100, $lighter: 100, $text: 900);

您也可以使用 Chrome 開發人員工具的內建無障礙工具,找出符合標準的顏色,或更新 Sass 中的個別顏色值。

驗證變更

再次檢查元素並驗證變更,現在主題應該有足夠的色彩對比度!

Chrome 開發人員工具檢查對比度足夠的主畫面按鈕元素

無障礙稽核

  • 所有網頁都有獨一無二的網頁標題
  • 顏色具有足夠的對比度
  • 🛑 HTML 應具有邏輯順序、名稱和角色
  • 🛑 螢幕閱讀器無法選取巢狀核取方塊
  • 🛑 螢幕閱讀器不會朗讀滑桿值
  • 🛑 螢幕閱讀器焦點位於色彩選擇器時,會退出對話方塊
  • 🛑 不會公布異動、錯誤和通知
  • 🛑 未啟用高對比模式

6. 使用語意式 HTML

原生 HTML 元素會擷取許多對無障礙功能而言相當重要的標準互動模式。雖然段落可以設定為 span 的樣式,div 也可以設定為按鈕的樣式,但語意 HTML 元素可確保螢幕閱讀器和鍵盤導覽功能瞭解 HTML 的互動和控制項。

撰寫 Angular 元件時,應盡可能直接重複使用這些原生元素,而不是重新實作支援良好的行為。這可確保網頁內容結構良好、內容流程自然,且索引標籤順序符合邏輯,協助使用者有效運用鍵盤瀏覽網站。

完成本節後,您的應用程式將通過下列稽核:

  • 🛑 HTML 應具有邏輯順序、名稱和角色

你可以在留言下方找到每個步驟:TODO: #6. Use Semantic HTML.

找出問題

  1. 開啟 VoiceOver。
  2. 使用 Tab 鍵瀏覽,然後按一下「我們的故事」分頁標籤。
  3. 請注意,分頁順序並非依序排列。
  4. 按一下「購買」Purchas
  5. 請注意,系統不會將按鈕辨識為按鈕。

Chrome 開發人員工具 Lighthouse 稽核結果顯示錯誤:標題元素並非依序遞減。排序正確且未略過層級的標題可傳達網頁的語意結構,讓使用者在運用輔助技術時更容易瀏覽及理解。瞭解詳情。

將 <div> 變更為 <button>

將自訂 <div> 替換為 Material 按鈕:

src/app/shop/shop.component.html

<button mat-flat-button 
  color="primary" 
  class="purchase-button"
  (click)="fauxPurchase()">
  Purchase
</button>

依序使用標題元素

重新排序文字以使用語意式 HTML,並使用 Angular Material 字體排版套用樣式:

src/app/about/about.component.html

<h2>Who are we?</h2>
<p class="mat-subheading-2">Have you ever thought, "wow, I love dumplings"?</p>
<p class="right mat-subheading-1">Who hasn't.</p>
<p class="center mat-subheading-1">We took it one step further and created Dumpling Dumpling,</p> 
<p class="center mat-subheading-1">double the dumpling, double the fun.</p>
<div class="spacer"></div>
<h2>How are we different?</h2>
<p class="mat-subheading-2">Handmade in San Francisco, California, we craft fully customizable dumplings. Glitter? Rainbows? Vegan? We do it all.</p>
<p class="right mat-subheading-2">This shop is concept only.</p>

驗證變更

再次開啟螢幕閱讀器,確認變更是否生效。VoiceOver 現在會辨識按鈕,並以邏輯順序朗讀文字!

無障礙稽核:

  • 所有網頁都有獨一無二的網頁標題
  • 顏色具有足夠的對比度
  • 語意式 HTML 可確保邏輯互動
  • 🛑 螢幕閱讀器無法選取巢狀核取方塊
  • 🛑 螢幕閱讀器不會朗讀滑桿值
  • 🛑 螢幕閱讀器焦點位於色彩選擇器時,會退出對話方塊
  • 🛑 不會公布異動、錯誤和通知
  • 🛑 未啟用高對比模式

7. 使用 Angular Material 建立可選取的控制項

無障礙服務的複雜互動模式之一是巢狀控制項。例如選單子項目或巢狀核取方塊。如何向使用者表明可以選取選項子群組,或前往上層選單項目?

在 Angular 中,盡可能簡化控制項,建立可導覽的元件,簡化選單和控制項。在本範例中,您會使用 Angular Material 的清單方塊,建構這個互動模式的其中一個範例。

完成本節後,您的應用程式將通過下列稽核:

  • 🛑 螢幕閱讀器無法選取巢狀核取方塊

你可以在留言下方找到每個步驟:TODO: #7. Create selectable controls with Angular Material.

找出問題

如要找出這個問題,請開啟螢幕閱讀器,然後嘗試選取巢狀核取方塊。

  1. 開啟 VoiceOver。
  2. 選取不同口味的餡料。
  3. 請注意,VoiceOver 讀取時,父項核取方塊不會指定子項。取消勾選「Bok Choy」(大白菜) 核取方塊後,您如何知道「Vegan」(全素) 核取方塊現在未勾選?

餡料核取方塊選單,選項包括:餡料、全素、小白菜、豆腐和香菇、肉類、雞肉、Impossible Meat

Angular Material 中的無障礙功能

您要將語意核取方塊換成 Angular Material 核取方塊,其中包含這類互動模式的內建知識。請注意,以 Material 取代元件並不能保證無障礙功能。與其他元件一樣,您需要手動測試,因為有許多方式會導致 Material 無法存取。

以 Material 核取方塊取代核取方塊

  1. 首先,請新增填料清單和變數,用來儲存所選填料口味:

src/app/shop/shop.component.ts

@Component(...)
export class ShopComponent implements OnInit {
  fillings: string[] = ['Bok Choy & Chili Crunch', 'Tofu & Mushroom', 'Chicken & Ginger', 'Impossible Meat & Spinach'];
  selectedFillings: string[] = [];

  fauxPurchase(): void {
    let flavor = '';
    this.selectedFillings.forEach(filling => {
      flavor = flavor + " " + filling
    })
  }
}
  1. 新增 <mat-selection-list>,取代這組雜亂的 HTML 核取方塊:

src/app/shop/shop.component.html

<mat-selection-list [(ngModel)]="selectedFillings" 
  aria-label="Dumpling fillings">
  <mat-list-option *ngFor="let flavor of fillings" 
    [value]="flavor" 
    color="primary">
    {{ flavor }}
  </mat-list-option>
</mat-selection-list>

您的 TODO 註解也會顯示在 src/app/shop/shop.component.scss 中,您可以在其中移除一些未使用的 Sass,以清理樣式。

驗證變更

再次開啟螢幕閱讀器,確認變更是否生效。現在可以選取核取方塊,並透過螢幕閱讀器更直覺地瀏覽內容!

內餡核取方塊選單,項目包括:內餡小白菜、辣椒酥豆腐、蘑菇雞肉、薑味 Impossible Meat、菠菜數量

無障礙稽核:

  • 所有網頁都有獨一無二的網頁標題
  • 顏色具有足夠的對比度
  • 語意式 HTML 可確保邏輯互動
  • 螢幕閱讀器可存取所有控制項
  • 🛑 螢幕閱讀器不會朗讀滑桿值
  • 🛑 螢幕閱讀器焦點位於色彩選擇器時,會退出對話方塊
  • 🛑 不會公布異動、錯誤和通知
  • 🛑 未啟用高對比模式

8. 使用 ARIA 提供控制項標籤

您修改了 Angular 應用程式的語意 HTML 和 Material 元件,但部分元件需要特定屬性,螢幕閱讀器才能完整瀏覽。

Web Accessibility Initiative 的無障礙網際網路應用程式規格 (WAI-ARIA 或 ARIA) 有助於解決無法透過原生 HTML 管理的問題。您可以指定屬性,修改元素轉換為無障礙功能樹狀結構的方式。

完成本節後,您的應用程式將通過下列稽核:

  • 🛑 螢幕閱讀器不會朗讀滑桿值

你可以在留言下方找到每個步驟:TODO: #8. Provide control labels with ARIA.

找出問題

如要找出這個問題,請開啟螢幕閱讀器並移動滑桿:

  1. 開啟 VoiceOver。
  2. 前往數量滑桿並變更值。
  3. 請注意,缺少值標籤。

Chrome 開發人員工具 Lighthouse 稽核結果顯示錯誤:ARIA 輸入欄位沒有可解讀的名稱。如果沒有可解讀的輸入欄位名稱,螢幕閱讀器只會讀出通用名稱,這樣仰賴螢幕閱讀器的使用者就無法知道這個輸入欄位的用途。瞭解詳情。

使用 ARIA 屬性

使用 aria-label 標籤控制 <mat-slider>

src/app/shop/shop.component.html

<mat-slider
  aria-label="Dumpling order quantity slider"
  id="quantity"
  name="quantity"
  color="primary"
  class="quantity-slider"
  [max]="13"
  [min]="1"
  [step]="1"
  [tickInterval]="1"
  thumbLabel
  [(ngModel)]="quantity">
</mat-slider>

驗證變更

再次開啟螢幕閱讀器,確認變更是否生效。現在可以移動滑桿了!

Chrome 開發人員工具 Lighthouse 稽核,通過螢幕閱讀器 ARIA 控制項的稽核。

無障礙稽核:

  • 所有網頁都有獨一無二的網頁標題
  • 顏色具有足夠的對比度
  • 語意式 HTML 可確保邏輯互動
  • 螢幕閱讀器可存取所有控制項
  • 滑桿使用 ARIA 屬性提供標籤
  • 🛑 螢幕閱讀器焦點位於色彩選擇器時,會退出對話方塊
  • 🛑 不會公布異動、錯誤和通知
  • 🛑 未啟用高對比模式

9. 新增 @angular/cdk/a11y 的強大功能

到目前為止,您都是使用內建的 Angular 工具來修正常見的無障礙問題。現在,我們來看看 CDK 的 a11y 模組,以及如何協助我們解決更複雜的 Angular 專屬問題。

本節結束時,您將繼續學習 Angular 無障礙功能模組工具。

您可以在註解下方找到這些步驟:TODO: #9. Add the power of @angular/cdk/a11y.

匯入模組

將模組新增至應用程式:

src/app/app.module.ts

import { A11yModule } from '@angular/cdk/a11y';

@NgModule({
  declarations: [...],
  imports: [
    A11yModule
  ],
  providers: [...],
  bootstrap: [...]
})

'@angular/cdk/a11y' 有什麼用途?

無障礙模組提供多種工具來提升無障礙程度,對元件作者特別實用。

在接下來的章節中,您將新增三項常見服務:FocusTrap、LiveAnnouncer 和 HighContrast。

如要進一步瞭解 @angular/cdk/a11y 提供的所有其他服務,請參閱「無障礙功能」。

10. 使用 FocusTrap 控制焦點

開啟對話方塊或強制回應時,使用者只能在其中互動。如果允許焦點逸出對話方塊,會混淆內容並建立狀態,導致使用者不知道自己位於網頁的哪個位置。

在 Angular 中,cdkTrapFocus 指令會在元素內保留 tab- 鍵焦點。這項功能適用於為模式對話方塊等元件建立無障礙體驗,因為焦點必須受到限制。

完成本節後,您的應用程式將通過下列稽核:

  • 🛑 螢幕閱讀器焦點位於色彩選擇器時,會退出對話方塊

你可以在留言下方找到這些步驟:TODO: #10. Control focus with FocusTrap.

找出問題

如要找出這個問題,請開啟螢幕閱讀器並開啟顏色挑選器對話方塊。

  1. 開啟 VoiceOver。
  2. 使用分頁導覽變更顏色。
  3. 檢查色彩挑選器中是否有直覺式焦點順序和焦點陷阱。

紫色和綠色主題的 Dumpling Time 商店網站,對話方塊開啟,可選取餃子皮顏色

新增 FocusTrap

cdkFocusTrap 可用於在自訂元件中捕捉及控管焦點順序。使用 mat-dialog-content 即可在對話方塊中擷取焦點,解決大多數問題。新增 cdkFocusInitial 屬性,在顏色挑選器對話方塊中,定義湯圓外皮顏色 <mat-selection-list> 的初始焦點區域。

src/app/shop/color-picker/color-picker-dialog/color-picker-dialog.component.html

<mat-selection-list #colors aria-label="Dumpling wrapper color" multiple="false" cdkFocusInitial>
  ...
</mat-selection-list>

驗證變更

再次開啟螢幕閱讀器,確認變更是否生效。對話方塊中的「變更顏色」現在會設為初始焦點!

無障礙稽核:

  • 所有網頁都有獨一無二的網頁標題
  • 顏色具有足夠的對比度
  • 語意式 HTML 可確保邏輯互動
  • 螢幕閱讀器可存取所有控制項
  • 滑桿使用 ARIA 屬性提供標籤
  • 顏色挑選器已正確鎖定焦點
  • 🛑 不會公布異動、錯誤和通知
  • 🛑 未啟用高對比模式

11. 透過 LiveAnnouncer 播報變更

當網頁上的內容有所變更時,必須通知螢幕閱讀器。試想一下,您嘗試提交表單或完成購買交易,但不知道系統已彈出錯誤訊息,導致表單無法提交。這太令人沮喪了!

LiveAnnouncer 會使用 aria-live 區域,為螢幕閱讀器使用者朗讀訊息,確保螢幕閱讀器會收到通知和網頁即時變更的通知。如要進一步瞭解 aria-live 區域,請參閱 W3C 的 WAI-ARIA。在 Angular 中,呼叫 LiveAnnouncer 做為服務,是比 aria-live 屬性更易於測試的解決方案。

完成本節後,您的應用程式將通過下列稽核:

  • 🛑 不會公布異動、錯誤和通知

你可以在留言下方找到這些步驟:TODO: #11. Announce changes with LiveAnnouncer.

找出問題

如要找出這個問題,請開啟螢幕閱讀器並選取「購買」,但不要填寫表單欄位:

  1. 開啟 VoiceOver。
  2. 使用分頁導覽變更顏色並進行虛假交易。
  3. 請注意,離開對話方塊時,系統不會指出選取的顏色,且購買項目不會讀取。

粉紅色和紅色主題的 Dumpling Time 商店網站,對話方塊開啟,可選取餃子皮顏色

在程式碼中加入 LiveAnnouncer

新增 LiveAnnouncer,並以字串形式播報顏色選項和虛假購買交易。在實際導入作業中,當您前往第三方付款系統或遇到表單錯誤時,系統可能會讀取這項資料。

  1. 選取顏色時新增公告:

src/app/shop/color-picker/color-picker-dialog/color-picker-dialog.component.ts

import { LiveAnnouncer } from '@angular/cdk/a11y';

@Component(...)
export class ColorPickerDialogComponent implements OnInit {
  constructor(
    public dialogRef: MatDialogRef<ColorPickerDialogComponent>,
    @Inject(MAT_DIALOG_DATA) public data: ColorDialogData,
    private liveAnnouncer: LiveAnnouncer) { }

  public changeColor(color: string): void {
    this.liveAnnouncer.announce(`Select color: ${color}`);
    this.dialogRef.close();
  }
}
  1. 在進行虛假交易時新增公告:

src/app/shop/shop.component.ts

import { LiveAnnouncer } from '@angular/cdk/a11y';

@Component(...)
export class ShopComponent implements OnInit {

  constructor(private liveAnnouncer: LiveAnnouncer) { }

  fauxPurchase(): void {
    let flavor = '...';
    const fakePurchase = `Purchase ${this.quantity} ${flavor}dumplings in the color ${this.color}!`;

    this.liveAnnouncer.announce(fakePurchase);
  }
}

驗證變更

再次開啟螢幕閱讀器,確認變更是否生效。現在系統會通知你錯誤!

無障礙稽核:

  • 所有網頁都有獨一無二的網頁標題
  • 顏色具有足夠的對比度
  • 語意式 HTML 可確保邏輯互動
  • 螢幕閱讀器可存取所有控制項
  • 滑桿使用 ARIA 屬性提供標籤
  • 顏色挑選器已正確鎖定焦點
  • 公布異動、錯誤和通知
  • 🛑 未啟用高對比模式

12. 啟用高對比模式

Microsoft Windows 支援名為「高對比模式」的無障礙功能。這個模式會變更所有應用程式 (包括網頁應用程式) 的外觀,大幅提高對比度。在 Angular 中,您希望在應用程式中尊重使用者的偏好設定。

HighContrastModeDetector 可讓您判斷瀏覽器目前是否處於高對比模式環境。

Internet Explorer、Microsoft Edge 和 Firefox 支援這個模式。Google Chrome 不支援 Windows 高對比模式。這項服務不會偵測 Chrome 高對比瀏覽器擴充功能新增的高對比模式。

完成本節後,您的應用程式將通過下列稽核:

  • 🛑 未啟用高對比模式

你可以在留言下方找到這些步驟:TODO: #12. Enable HighContrast mode.

找出問題

如要找出這個問題,請在 Internet Explorer、Microsoft Edge 或 Firefox 中開啟應用程式,開啟高對比模式,並觀察沒有任何變化:

  1. 在 Internet Explorer、Microsoft Edge 或 Firefox 中開啟應用程式。
  2. 開啟高對比模式。
  3. 請注意,應用程式並未變更。

新增高對比模式支援

styles.scss 中,使用 @angular/cdk/a11y 提供的 cdk-high-contrast mixin,在高對比模式中為按鈕新增外框:

src/app/shop/shop.component.scss

@use '@angular/cdk';

.purchase-button {
    border-radius: 5px;
    background-color: mat.get-color-from-palette(mat.$pink-palette, A100);

    @include cdk-high-contrast {
      outline: solid 1px;
      background-color: mat.get-color-from-palette(mat.$pink-palette, 50);
    }
}

:host-context(.dark-theme) {
  .purchase-button {
    background-color: mat.get-color-from-palette(mat.$light-green-palette, A100);

    @include cdk-high-contrast {
      outline: solid 1px;
      background-color: mat.get-color-from-palette(mat.$light-green-palette, 50);
    }
  }
}

驗證變更

重新整理應用程式,確認變更已生效。您已在高對比模式中為按鈕新增外框!

Dumpling Time 商店網站採用紅色和粉紅色主題,並開啟高對比模式,購買按鈕現在以粗紅外框強烈聚焦 Dumpling Time 商店網站採用藍色和綠色主題,並開啟高對比模式,購買按鈕現在以粗藍色外框醒目顯示

無障礙稽核:

  • 所有網頁都有獨一無二的網頁標題
  • 顏色具有足夠的對比度
  • 語意式 HTML 可確保邏輯互動
  • 螢幕閱讀器可存取所有控制項
  • 滑桿使用 ARIA 屬性提供標籤
  • 顏色挑選器已正確鎖定焦點
  • 公布異動、錯誤和通知
  • 已啟用高對比模式

13. 恭喜!

恭喜!您已解決 Angular 應用程式中常見的網頁無障礙問題。🎉

如要查看所有解決方案,請查看 main 分支。

以紅色和粉紅色為主題的 Dumpling Time 商店網站,顯示本程式碼研究室中的所有變更 以藍色和綠色主題顯示的 Dumpling Time 商店網站,會顯示本程式碼研究室中的所有變更 Chrome 開發人員工具 Lighthouse 稽核,分數為 100/100

您現在已瞭解解決 Angular 應用程式中八個常見無障礙陷阱的重要步驟。

瞭解詳情

歡迎參考下列程式碼研究室:

請參閱下列資料: