Xây dựng các ứng dụng Angular dễ tiếp cận hơn

1. Trước khi bắt đầu

biểu trưng Angular màu đen

Hỗ trợ tiếp cận là một phần quan trọng trong quá trình phát triển web, đảm bảo rằng người dùng có thể nhận biết, hiểu, điều hướng và tương tác với ứng dụng. Trên thực tế, cứ 4 người lớn ở Hoa Kỳ thì có 1 người bị khuyết tật ảnh hưởng đến các hoạt động chính trong cuộc sống. Trên toàn thế giới, khoảng 15% dân số thế giới (hơn 1 tỷ người) mắc một dạng khuyết tật nào đó, trong đó khoảng 2 đến 4% phải đối mặt với những khó khăn đáng kể.

Các tình trạng thông thường ảnh hưởng đến việc một người sử dụng web bao gồm khi mù hoặc thị lực kém, khiếm thính hoặc suy giảm thính lực, kỹ năng vận động bị hạn chế, khuyết tật nhận thức và mù màu — và đây chỉ là một danh sách chưa đầy đủ.

Trong khoá học này, a11y là viết tắt của tính năng hỗ trợ tiếp cận. Lưu ý rằng a theo sau là 11 ký tự và y.

Để biết thông tin giới thiệu chi tiết về các vấn đề và kỹ thuật thiết kế ứng dụng hỗ trợ tiếp cận, hãy xem phần Hỗ trợ tiếp cận.

Sản phẩm bạn sẽ tạo ra

  • Sử dụng các phương pháp hay nhất và kỹ thuật tích hợp sẵn để giải quyết các vấn đề thường gặp về hỗ trợ tiếp cận trên web trong ứng dụng minh hoạ Dumpling Shop Angular
  • Đáp ứng tất cả nguyên tắc hỗ trợ tiếp cận, WCAG 2.0 và ARIA 1.2, đồng thời vượt qua các quy trình kiểm tra khả năng hỗ trợ tiếp cận của axe và Lighthouse.

Trang web của cửa hàng Dumpling Time có giao diện màu hồng và đỏ Trang web của cửa hàng Dumpling Time có giao diện màu tím và xanh lục

Kiến thức bạn sẽ học được

Bạn sẽ tìm hiểu về 8 vấn đề thường gặp về khả năng tiếp cận trong ứng dụng Angular ảnh hưởng đến người dùng, cách xác định và cách khắc phục các vấn đề đó. Cụ thể hơn, bạn:

  • Sử dụng Công cụ dành cho nhà phát triển Chrome, Lighthouse và rìu của Google để kiểm tra khả năng hỗ trợ tiếp cận của ứng dụng
  • Giải quyết các vấn đề về ứng dụng trang đơn (SPA) bằng tiêu đề trang riêng biệt
  • Khắc phục các vấn đề về độ tương phản màu thấp cho người dùng có thị lực kém
  • Sử dụng HTML ngữ nghĩa để đảm bảo trình đọc màn hình điều hướng trang chính xác
  • Sử dụng Angular Material và các chế độ điều khiển không lồng nhau để đảm bảo trình đọc màn hình có thể truy cập vào tất cả các chế độ điều khiển
  • Thêm tính năng hỗ trợ ARIA cho trình đọc màn hình
  • Nhập và sử dụng gói a11y của Angular CDK
  • Sử dụng FocusTrap để điều hướng trình đọc màn hình thành phần tuỳ chỉnh
  • Thông báo về thông báo bằng LiveAnnouncer của CDK
  • Phát hiện người dùng có chế độ HighContrast và triển khai giao diện có độ tương phản cao

Bạn cần có

2. Bắt đầu thiết lập

Nhận

Mọi thứ bạn cần cho dự án này đều nằm trong kho lưu trữ GitHub. Để bắt đầu, hãy nhân bản mã và mở mã đó trong môi trường phát triển mà bạn yêu thích.

Nhân bản kho lưu trữ và phân phát ứng dụng

Bạn nên dùng VSCode hoặc IDE cục bộ để thực hiện lớp học lập trình này.

  1. Mở một thẻ trình duyệt mới rồi truy cập vào https://github.com/googlecodelabs/angular-accessibility.
  2. Phát triển nhánh và sao chép kho lưu trữ và cd angular-accessibility/ vào kho lưu trữ.
  3. Hãy xem nhánh mã khởi động git checkout get-started.
  4. Mở mã trong VSCode hoặc IDE mà bạn muốn dùng.
  5. Chạy npm install để cài đặt các phần phụ thuộc cần thiết để chạy máy chủ.
  6. Chạy ng serve để chạy máy chủ.
  7. Mở một thẻ trình duyệt đến http://localhost:4200.

3. Thiết lập đường cơ sở

Điểm xuất phát của bạn là gì?

Điểm xuất phát của bạn là một ứng dụng nhà hàng cơ bản được thiết kế cho lớp học lập trình này. Mã đã được đơn giản hoá để thể hiện các khái niệm trong lớp học lập trình này và có ít chức năng.

Trang web của cửa hàng Dumpling Time có giao diện màu tím và xanh lục

Khám phá bản minh hoạ

Để bắt đầu, hãy tìm hiểu ba chức năng của ứng dụng:

  1. Sử dụng thanh điều hướng để xem các tuyến Cửa hàng của chúng tôi, Câu chuyện của chúng tôiTìm chúng tôi, đồng thời xem thông tin chi tiết về công ty bán bánh bao.
  2. Thay đổi giao diện để bật/tắt chế độ sáng và tối.
  3. Tuỳ chỉnh nhân bánh bao, số lượng và màu sắc của bánh bao trong đơn đặt hàng.
  4. Chọn Mua hàng để ghi lại đơn đặt hàng tuỳ chỉnh của bạn trong bảng điều khiển.

Sử dụng Angular để giải quyết các vấn đề thường gặp về hỗ trợ tiếp cận trên web

Trong lớp học lập trình này, bạn sẽ tập trung vào khả năng hỗ trợ tiếp cận của các tính năng hiện có trong ứng dụng này. Bạn sẽ bắt đầu bằng cách xác định các vấn đề về a11y trong ứng dụng, sau đó chuyển 🛑 thành ✅ bằng cách triển khai một giải pháp.

Làm cách nào để biết cần khắc phục vấn đề gì?

Bắt đầu mỗi ví dụ bằng cách nhận dạng vấn đề về khả năng hỗ trợ tiếp cận bằng cách kết hợp kiểm thử thủ công và tự động.

Trong trạng thái hiện tại của web, việc kiểm tra khả năng hỗ trợ tiếp cận theo cách thủ công là bắt buộc.

Bạn có những công cụ có thể xác định các vấn đề về khả năng hỗ trợ tiếp cận, nhưng không công cụ nào có thể chứng nhận rằng một ứng dụng hoàn toàn có thể truy cập được. Kiểm thử thủ công đảm bảo rằng bạn kiểm thử nhiều khái niệm về hỗ trợ tiếp cận, bao gồm cả thứ tự nội dung hợp lý và tính năng tương đương.

Kiểm thử thủ công

Để kiểm tra khả năng hỗ trợ tiếp cận trong khoá học này theo cách thủ công, bạn cần bật trình đọc màn hình tích hợp trên máy tính rồi điều hướng qua ứng dụng bằng thao tác trên bàn phím. Để biết thêm thông tin, hãy xem bài viết Ngữ nghĩa và trình đọc màn hình.

Thực hành bằng cách bật trình đọc màn hình và thao tác trên màn hình.

Bạn có thể sử dụng VoiceOver tích hợp sẵn trên macOS. Nhấp vào System Preferences (Lựa chọn ưu tiên về hệ thống) > Accessibility (Trợ năng) > VoiceOver (VoiceOver) > Enable VoiceOver to turn it on (Bật VoiceOver để bật tính năng này). Để bật/tắt tính năng VoiceOver, hãy nhấn nhanh vào nút TouchID 3 lần trong khi giữ phím Command.

Trong khoá học này, bạn chủ yếu kiểm tra các vấn đề theo cách thủ công và sử dụng các công cụ tự động để hỗ trợ việc kiểm tra các tính năng tự động cụ thể.

Kiểm thử tự động

Bạn cũng có thể sử dụng một số công cụ phát triển để tự động hoá và kiểm tra ứng dụng của mình. Các công cụ này cho phép bạn kiểm tra những thông tin như sự hiện diện của văn bản thay thế trên hình ảnh hoặc tỷ lệ tương phản của màu văn bản. Bạn có thể coi các công cụ này là công cụ tìm lỗi mã nguồn; chúng có thể nhận ra rằng văn bản thay thế có mặt, nhưng bạn phải kiểm tra thủ công để đảm bảo rằng nội dung đó hợp lý và có giá trị.

Lighthouse và Công cụ cho nhà phát triển Chrome

  1. Mở Công cụ cho nhà phát triển Chrome.
  2. Chọn thẻ Lighthouse rồi chọn hộp đánh dấu Hỗ trợ tiếp cận.
  3. Nhấp vào Tạo báo cáo để chạy quy trình kiểm tra Lighthouse về khả năng hỗ trợ tiếp cận.

Thẻ ví dụ về Lighthouse có nút Tạo báo cáo trong thẻ Công cụ của Chrome cho nhà phát triển

Rìu

  1. Cài đặt tiện ích Công cụ cho nhà phát triển rìu. Bạn có thể phải khởi động lại trình duyệt để xem tiện ích này.
  2. Mở Công cụ cho nhà phát triển Chrome.
  3. Chọn thẻ axe DevTools rồi chọn Scan all of my page (Quét tất cả trang của tôi) để chạy quy trình quét bằng axe DevTools.

Tìm lỗi mã nguồn

Bạn có thể sử dụng các quy tắc ESLint của Angular để tìm lỗi mã nguồn cho các thuộc tính a11y có thể tự động hoàn thành.

Trong eslint.json, hãy thêm các nội dung sau đây cho khả năng hỗ trợ tiếp cận:

"@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

Để biết thêm thông tin, hãy xem các quy tắc ESLint mới nhất trên GitHub.

Điểm xuất phát của bạn

Khi sử dụng các phương pháp kiểm thử mới, bạn có thể xác định các vấn đề sau trong ứng dụng của mình bằng tính năng kiểm tra bằng Lighthouse và rìu, cũng như VoiceOver thủ công:

Kiểm tra Lighthouse của Chrome cho nhà phát triển với điểm số là 82

Kiểm tra khả năng hỗ trợ tiếp cận:

  • 🛑 Tất cả các trang đều có cùng tiêu đề trang
  • 🛑 Các phần tử phải có đủ độ tương phản về màu sắc
  • 🛑 HTML phải có thứ tự, tên và vai trò hợp lý
  • 🛑 Trình đọc màn hình không thể chọn các hộp đánh dấu lồng nhau
  • 🛑 Trình đọc màn hình không đọc giá trị của thanh trượt
  • 🛑 Tiêu điểm của trình đọc màn hình trong công cụ chọn màu sẽ thoát khỏi hộp thoại
  • 🛑 Không thông báo về các thay đổi, lỗi và thông báo
  • 🛑 Chế độ HighContrast chưa được bật

4. Xác định tiêu đề trang riêng biệt

Việc cung cấp tiêu đề trang độc đáo, súc tích giúp người dùng sử dụng các dịch vụ của a11y nhanh chóng hiểu được nội dung và mục đích của trang web. Tiêu đề trang rất quan trọng đối với người dùng khiếm thị vì đó là phần tử trang đầu tiên được phần mềm đọc màn hình công bố.

Angular là ứng dụng trang đơn và do đó, phần lớn các quá trình chuyển đổi, chẳng hạn như chuyển sang một trang mới, không liên quan đến việc tải lại một trang. Cho đến gần đây, điều này có nghĩa là mỗi trang đều có tiêu đề trang giống hệt nhau và không cung cấp giá trị nào để hiểu nội dung hoặc mục đích của trang.

Trong Angular phiên bản 14, Bộ định tuyến đã thêm một phương thức tích hợp sẵn để xác định tiêu đề trang duy nhất ngay từ đầu. Điều này mang đến một cách tiếp cận đơn giản để đảm bảo nhà phát triển làm theo các phương pháp hay nhất về tiêu đề trang.

Khi kết thúc phần này, ứng dụng của bạn sẽ vượt qua quy trình kiểm tra sau:

  • 🛑 Tất cả các trang đều có cùng tiêu đề trang

Bạn có thể tìm thấy từng bước trong số này trong nhận xét: TODO: #4. Define unique page titles.

Xác định vấn đề

Để xác định vấn đề này, hãy bật trình đọc màn hình rồi di chuyển giữa các thẻ Cửa hàng của chúng tôi, Câu chuyện của chúng tôiTìm chúng tôi để xem các tiêu đề trang:

  1. Bật VoiceOver.
  2. Sử dụng tính năng điều hướng bằng thẻ để di chuyển giữa các trang.
  3. Xác minh tiêu đề trang luôn là a11y trong Angular.

Đây là vấn đề vì tiêu đề trang phải là duy nhất để người dùng có thể nhanh chóng hiểu được nội dung của trang mà không cần phải di chuyển qua trang đó.

Trình duyệt Chrome có 3 thẻ đang mở với tiêu đề trang giống hệt nhau: "a11y trong Angular"

Thêm tiêu đề trang có ý nghĩa

Nếu một trang hoặc chế độ xem thay đổi, bạn cần quản lý tiêu đề trang đúng cách. Để khắc phục vấn đề này, bạn sử dụng thuộc tính Router.title tích hợp sẵn của Angular để xác định tiêu đề riêng biệt cho từng trang.

  1. Thêm một tiêu đề riêng biệt vào mỗi tuyến trong số 3 tuyến đã xác định:

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 },
];

Thao tác này sẽ tự động nhập và sử dụng Router's Title Service để quản lý việc thay đổi tiêu đề trang trên thanh điều hướng cho khớp với thuộc tính tiêu đề được xác định trong các tuyến của chúng ta. Bạn cũng có thể quản lý những tiêu đề trang phức tạp hơn bằng TitleStrategy tuỳ chỉnh.

Xác minh thay đổi

Bật lại trình đọc màn hình và xác minh nội dung thay đổi. Giờ đây, các trang sẽ có tiêu đề riêng biệt!

Trình duyệt Chrome có 3 thẻ đang mở với tiêu đề trang riêng biệt: "Our Shop - a11y in Angular" (Cửa hàng của chúng tôi – Hỗ trợ tiếp cận trong Angular), "Our Story - a11y in Angular" (Câu chuyện của chúng tôi – Hỗ trợ tiếp cận trong Angular), "Find Us - a11y in Angular" (Tìm chúng tôi – Hỗ trợ tiếp cận trong Angular)

Kiểm tra khả năng hỗ trợ tiếp cận:

  • Tất cả các trang đều có tiêu đề riêng biệt
  • 🛑 Các phần tử phải có độ tương phản màu phù hợp
  • 🛑 HTML phải có thứ tự, tên và vai trò hợp lý
  • 🛑 Trình đọc màn hình không thể chọn các hộp đánh dấu lồng nhau
  • 🛑 Trình đọc màn hình không đọc giá trị của thanh trượt
  • 🛑 Tiêu điểm của trình đọc màn hình trong công cụ chọn màu sẽ thoát khỏi hộp thoại
  • 🛑 Không thông báo về các thay đổi, lỗi và thông báo
  • 🛑 Chế độ HighContrast chưa được bật

5. Đảm bảo độ tương phản màu phù hợp

Thiết kế của bạn có thể trông rất tuyệt, nhưng sẽ không tuyệt nếu những người khiếm thị như mù màu không đọc được nội dung của bạn. Nguyên tắc truy cập nội dung web (WCAG 2.0) xác định một loạt tỷ lệ tương phản màu để đảm bảo nội dung có thể truy cập được. Trong Angular và trên web, bạn có thể xác định các bảng màu nhằm đảm bảo các thành phần của bạn đáp ứng các tiêu chuẩn này và người dùng có thị lực kém và người bị mù màu đều có thể nhìn thấy các bảng màu.

Khi kết thúc phần này, ứng dụng của bạn sẽ vượt qua quy trình kiểm tra sau:

  • 🛑 Các phần tử phải có độ tương phản màu phù hợp

Bạn có thể xem từng bước này trong phần bình luận: TODO: #5. Ensure adequate color contrast.

Sử dụng Công cụ cho nhà phát triển Chrome để xác định các vấn đề về độ tương phản thấp

Để xác định vấn đề này, hãy sử dụng Công cụ cho nhà phát triển Chrome để kiểm tra các phần tử trong ứng dụng.

  1. Sử dụng công cụ kiểm tra để xem các nút biểu tượng trình đơn. Bạn có thể thấy độ tương phản là 1,85, thấp hơn nhiều so với các yêu cầu của WCAG.

Công cụ của Chrome cho nhà phát triển kiểm tra phần tử của nút Màn hình chính có độ tương phản thấp

  1. Chạy quy trình kiểm tra Hỗ trợ tiếp cận trong Lighthouse hoặc quy trình quét của axe để xem các vấn đề về tỷ lệ tương phản này.

Kết quả kiểm tra Lighthouse của Công cụ của Chrome cho nhà phát triển có lỗi: "Màu nền trước và nền sau không có đủ tỷ lệ tương phản"

Thay đổi màu giao diện Material

Bảng phối màu thành phần được xác định trong giao diện Material tuỳ chỉnh. Bạn cập nhật giá trị giao diện để đáp ứng các nguyên tắc về tỷ lệ tương phản màu.

Cập nhật giao diện Material để sử dụng màu văn bản tối hơn, tăng tỷ lệ tương phản của các biểu tượng:

src/styles.scss

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

Bạn cũng có thể sử dụng công cụ hỗ trợ tiếp cận tích hợp sẵn trong Công cụ cho nhà phát triển Chrome để tìm màu đáp ứng các tiêu chuẩn hoặc cập nhật từng giá trị màu trong Sass.

Xác minh thay đổi

Kiểm tra lại các phần tử và xác minh các thay đổi của bạn, giao diện của chúng ta hiện đã có đủ tỷ lệ tương phản màu!

Công cụ của Chrome cho nhà phát triển kiểm tra phần tử của nút Trang chủ có đủ độ tương phản

Kiểm tra khả năng hỗ trợ tiếp cận

  • Tất cả các trang đều có tiêu đề trang riêng biệt
  • Màu sắc có tỷ lệ tương phản đủ
  • 🛑 HTML phải có thứ tự, tên và vai trò hợp lý
  • 🛑 Trình đọc màn hình không thể chọn các hộp đánh dấu lồng nhau
  • 🛑 Trình đọc màn hình không đọc giá trị của thanh trượt
  • 🛑 Tiêu điểm của trình đọc màn hình trong công cụ chọn màu sẽ thoát khỏi hộp thoại
  • 🛑 Không thông báo về các thay đổi, lỗi và thông báo
  • 🛑 Chế độ HighContrast chưa được bật

6. Sử dụng HTML có ngữ nghĩa

Các phần tử HTML gốc ghi lại một số mẫu tương tác chuẩn quan trọng đối với khả năng hỗ trợ tiếp cận. Mặc dù bạn có thể tạo kiểu cho một đoạn văn bản dưới dạng span và tạo kiểu cho một div dưới dạng nút, nhưng phần tử HTML ngữ nghĩa đảm bảo rằng trình đọc màn hình và thao tác điều hướng bằng bàn phím hiểu được các hoạt động tương tác và các chế độ điều khiển của HTML.

Khi tạo thành phần Angular, bạn nên sử dụng lại trực tiếp các phần tử gốc này khi có thể, thay vì triển khai lại các hành vi được hỗ trợ tốt. Điều này đảm bảo rằng trang có cấu trúc nội dung tốt và luồng nội dung tự nhiên, đồng thời thẻ được sắp xếp theo thứ tự hợp lý để hỗ trợ người dùng điều hướng trang web bằng cách sử dụng bàn phím một cách hiệu quả.

Khi kết thúc phần này, ứng dụng của bạn sẽ vượt qua quy trình kiểm tra sau:

  • 🛑 HTML phải có thứ tự, tên và vai trò hợp lý

Bạn có thể xem từng bước này trong phần bình luận: TODO: #6. Use Semantic HTML.

Xác định vấn đề

  1. Bật VoiceOver.
  2. Sử dụng phím tab để nhấp vào thẻ Câu chuyện của chúng tôi.
  3. Lưu ý thứ tự thẻ không tuần tự.
  4. Nhấp vào Mua.
  5. Lưu ý rằng nút này không được nhận dạng là nút.

Kết quả kiểm tra lỗi Ngọn hải đăng công cụ của Chrome cho nhà phát triển: Các phần tử tiêu đề không theo thứ tự giảm dần theo tuần tự, tiêu đề được sắp xếp đúng cách mà không bỏ qua các cấp độ truyền tải cấu trúc ngữ nghĩa của trang, giúp bạn dễ dàng điều hướng và hiểu rõ hơn khi sử dụng công nghệ hỗ trợ. Tìm hiểu thêm.

Thay đổi <div> thành <button>

Thay thế <div> tuỳ chỉnh bằng nút Material:

src/app/shop/shop.component.html

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

Sử dụng các phần tử tiêu đề theo tuần tự

Sắp xếp lại văn bản để sử dụng HTML có ngữ nghĩa và áp dụng kiểu bằng kiểu chữ 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>

Xác minh các thay đổi

Bật lại trình đọc màn hình và xác minh các thay đổi. VoiceOver hiện đã nhận dạng được nút và văn bản được đọc theo thứ tự hợp lý!

Kiểm tra khả năng hỗ trợ tiếp cận:

  • Tất cả các trang đều có tiêu đề riêng biệt
  • Màu sắc có tỷ lệ tương phản đủ
  • HTML có ngữ nghĩa đảm bảo tương tác hợp lý
  • 🛑 Trình đọc màn hình không thể chọn các hộp đánh dấu lồng nhau
  • 🛑 Trình đọc màn hình không đọc giá trị của thanh trượt
  • 🛑 Tiêu điểm của trình đọc màn hình trong công cụ chọn màu sẽ thoát khỏi hộp thoại
  • 🛑 Không thông báo về các thay đổi, lỗi và thông báo
  • 🛑 Chế độ Tương phản cao chưa bật

7. Tạo các thành phần điều khiển có thể chọn bằng Angular Material

Một mẫu tương tác phức tạp cho các dịch vụ hỗ trợ tiếp cận là các thành phần điều khiển lồng nhau. Hãy nghĩ đến các mục con trong trình đơn hoặc các hộp đánh dấu lồng nhau. Làm cách nào để cho người dùng biết rằng bạn có thể chọn một nhóm con các tuỳ chọn hoặc chuyển đến một mục trình đơn mẹ?

Trong Angular, hãy đơn giản hoá các trình đơn và chức năng điều khiển để tạo các thành phần có thể điều hướng bằng cách đơn giản hoá các thành phần điều khiển nhiều nhất có thể. Trong ví dụ này, bạn sử dụng hộp danh sách của Angular Material để tạo một ví dụ về mẫu tương tác này.

Khi kết thúc phần này, ứng dụng của bạn sẽ vượt qua quy trình kiểm tra sau:

  • 🛑 Không chọn được hộp đánh dấu lồng nhau cho trình đọc màn hình

Bạn có thể xem từng bước này trong phần bình luận: TODO: #7. Create selectable controls with Angular Material.

Xác định vấn đề

Để xác định sự cố này, chúng ta sẽ bật trình đọc màn hình và thử chọn một hộp kiểm lồng nhau.

  1. Bật VoiceOver.
  2. Chọn nhiều hương vị nhân bánh.
  3. Lưu ý rằng các hộp đánh dấu cấp độ gốc không chỉ định phần tử con khi được đọc bằng VoiceOver. Làm cách nào để biết hộp đánh dấu Vegan bị bỏ chọn sau khi bạn bỏ chọn hộp đánh dấu Bok Choy?

Trình đơn hộp đánh dấu cho phần nhân với các lựa chọn: Phần nhân Rau bina đậu phụ và thịt nấm shiitake Thịt gà Impossible

Hỗ trợ tiếp cận trong Angular Material

Bạn thay thế hộp đánh dấu ngữ nghĩa bằng hộp đánh dấu Angular Material, trong đó chứa kiến thức tích hợp sẵn về mẫu tương tác này. Xin lưu ý rằng việc thay thế các thành phần bằng Material không đảm bảo khả năng hỗ trợ tiếp cận. Giống như mọi thành phần khác, bạn cần kiểm thử theo cách thủ công vì có rất nhiều cách triển khai Material mà không thể truy cập được.

Thay thế hộp đánh dấu bằng hộp đánh dấu Material

  1. Trước tiên, hãy thêm danh sách nhân mới và một biến để lưu trữ các hương vị nhân đã chọn:

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. Thêm <mat-selection-list> để thay thế nhóm hộp đánh dấu HTML lộn xộn này:

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>

Các nhận xét TODO cũng cho biết vị trí bạn có thể xoá một số Sass không dùng đến trong src/app/shop/shop.component.scss để dọn dẹp kiểu.

Xác minh thay đổi

Bật lại trình đọc màn hình và xác minh các thay đổi. Giờ đây, bạn có thể chọn và điều hướng hộp đánh dấu một cách trực quan hơn bằng trình đọc màn hình!

Thực đơn có hộp đánh dấu gồm các món: Fillings Bok Choy &Chili Crunch Tofu &CanhroomGà &Ginger Diễm Thịt &Rau chân vịt Số lượng

Kiểm tra khả năng hỗ trợ tiếp cận:

  • Tất cả các trang đều có tiêu đề riêng biệt
  • Màu sắc có tỷ lệ tương phản đủ
  • HTML có ngữ nghĩa đảm bảo tương tác hợp lý
  • Trình đọc màn hình có thể truy cập vào tất cả các chế độ điều khiển
  • 🛑 Trình đọc màn hình không đọc giá trị của thanh trượt
  • 🛑 Tiêu điểm của trình đọc màn hình trong công cụ chọn màu sẽ thoát khỏi hộp thoại
  • 🛑 Không thông báo về các thay đổi, lỗi và thông báo
  • 🛑 Chế độ Tương phản cao chưa bật

8. Cung cấp nhãn kiểm soát bằng ARIA

Bạn đã sửa đổi các thành phần HTML ngữ nghĩa và Material của ứng dụng Angular. Tuy nhiên, một số thành phần đòi hỏi các thuộc tính cụ thể để trình đọc màn hình điều hướng đầy đủ.

Thông số kỹ thuật về Ứng dụng đa dạng thức có thể truy cập của Sáng kiến Hỗ trợ tiếp cận trên web (WAI-ARIA hoặc ARIA) giúp giải quyết các vấn đề không thể quản lý bằng HTML gốc. Thuộc tính này cho phép bạn chỉ định các thuộc tính sửa đổi cách một phần tử được dịch sang cây hỗ trợ tiếp cận.

Khi kết thúc phần này, ứng dụng của bạn sẽ vượt qua quy trình kiểm tra sau:

  • 🛑 Trình đọc màn hình không đọc giá trị của thanh trượt

Bạn có thể tìm thấy từng bước trong số này trong phần nhận xét: TODO: #8. Provide control labels with ARIA.

Xác định vấn đề

Để xác định sự cố này, hãy bật trình đọc màn hình và di chuyển thanh trượt của bạn:

  1. Bật VoiceOver.
  2. Chuyển đến thanh trượt số lượng và thay đổi giá trị.
  3. Lưu ý rằng nhãn giá trị bị thiếu.

Kết quả kiểm tra Lighthouse của Chrome DevTools có lỗi:  Tên các trường nhập của ARIA ở trạng thái không thể tiếp cận Khi một trường nhập dữ liệu không có tên thành phần hỗ trợ tiếp cận, thì trình đọc màn hình sẽ gọi trường đó bằng tên gọi chung, khiến người dùng trình đọc màn hình không dùng được trường này. Tìm hiểu thêm.

Sử dụng các thuộc tính ARIA

Kiểm soát nhãn bằng cách sử dụng từ aria-label đến <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>

Xác minh thay đổi

Bật lại trình đọc màn hình và xác minh các thay đổi. Bây giờ, bạn có thể di chuyển thanh trượt!

Kết quả kiểm tra Lighthouse trong Công cụ của Chrome cho nhà phát triển, trong đó kiểm tra thành công các chế độ điều khiển ARIA của trình đọc màn hình.

Kiểm tra khả năng hỗ trợ tiếp cận:

  • Tất cả các trang đều có tiêu đề riêng biệt
  • Màu sắc có tỷ lệ tương phản đủ
  • HTML có ngữ nghĩa đảm bảo tương tác hợp lý
  • Trình đọc màn hình có thể truy cập vào tất cả các chế độ điều khiển
  • Thanh trượt sử dụng các thuộc tính ARIA để cung cấp nhãn
  • 🛑 Tiêu điểm của trình đọc màn hình trong công cụ chọn màu sẽ thoát khỏi hộp thoại
  • 🛑 Không thông báo về các thay đổi, lỗi và thông báo
  • 🛑 Chế độ HighContrast chưa được bật

9. Thêm sức mạnh của @angular/cdk/a11y

Cho đến nay, bạn đã dựa vào công cụ Angular tích hợp để khắc phục các vấn đề thường gặp về a11y. Bây giờ, hãy tìm hiểu mô-đun a11y của CDK và cách mô-đun này có thể giúp chúng ta giải quyết các vấn đề phức tạp và cụ thể về Angular.

Khi kết thúc phần này, bạn sẽ tiếp tục khoá học này bằng công cụ mô-đun Angular a11y.

Bạn có thể tìm thấy các bước này trong phần bình luận: TODO: #9. Add the power of @angular/cdk/a11y.

Nhập mô-đun

Thêm mô-đun vào ứng dụng:

src/app/app.module.ts

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

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

'@angular/cdk/a11y' làm gì?

Mô-đun a11y cung cấp một số công cụ để cải thiện khả năng hỗ trợ tiếp cận và đặc biệt hữu ích cho các tác giả thành phần.

Trong các phần sau, bạn sẽ thêm ba dịch vụ phổ biến: FocusTrap, LiveAnnouncer và HighContrast.

Để biết thêm thông tin về tất cả các dịch vụ khác mà @angular/cdk/a11y cung cấp, hãy xem phần Hỗ trợ tiếp cận.

10. Kiểm soát tiêu điểm bằng FocusTrap

Khi một hộp thoại hoặc cửa sổ phụ mở, người dùng chỉ tương tác bên trong hộp thoại hoặc cửa sổ đó. Việc cho phép tiêu điểm thoát ra bên ngoài hộp thoại sẽ kết hợp các ngữ cảnh và tạo trạng thái mà người dùng không biết họ đang ở đâu trên trang.

Trong Angular, lệnh cdkTrapFocus sẽ bẫy tiêu điểm khoá tab- trong một phần tử. Phương thức này được dùng để tạo trải nghiệm hỗ trợ tiếp cận cho các thành phần như hộp thoại phương thức, trong đó tiêu điểm phải bị ràng buộc.

Khi kết thúc phần này, ứng dụng của bạn sẽ vượt qua quy trình kiểm tra sau đây:

  • 🛑 Tiêu điểm của trình đọc màn hình trong công cụ chọn màu sẽ thoát khỏi hộp thoại

Bạn có thể tìm thấy các bước này trong phần bình luận: TODO: #10. Control focus with FocusTrap.

Xác định vấn đề

Để xác định vấn đề này, hãy bật trình đọc màn hình rồi mở hộp thoại công cụ chọn màu.

  1. Bật VoiceOver.
  2. Sử dụng tính năng điều hướng bằng phím tab để thay đổi màu.
  3. Kiểm tra để xem thứ tự lấy nét trực quan và tính năng giữ tiêu điểm trong bộ chọn màu.

Trang web của cửa hàng Dumpling Time có giao diện tím và xanh lục với hộp thoại đang mở để chọn màu gói bánh bao

Thêm FocusTrap

Bạn có thể dùng cdkFocusTrap để chặn và kiểm soát thứ tự tiêu điểm trong các thành phần tuỳ chỉnh. Chỉ cần sử dụng mat-dialog-content là đủ để giải quyết hầu hết vấn đề bằng cách giữ lại tiêu điểm trong hộp thoại. Thêm thuộc tính cdkFocusInitial để xác định vùng tiêu điểm ban đầu trên màu của trình bao bọc bánh bao <mat-selection-list> trong hộp thoại công cụ chọn màu.

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>

Xác minh các thay đổi

Bật lại trình đọc màn hình và xác minh nội dung thay đổi. Tiêu điểm ban đầu được đặt trên Change Color (Thay đổi màu) trong hộp thoại!

Kiểm tra khả năng hỗ trợ tiếp cận:

  • Tất cả các trang đều có tiêu đề riêng biệt
  • Màu sắc có tỷ lệ tương phản đủ
  • HTML có ngữ nghĩa đảm bảo tương tác hợp lý
  • Trình đọc màn hình có thể truy cập vào tất cả các chế độ điều khiển
  • Thanh trượt sử dụng các thuộc tính ARIA để cung cấp nhãn
  • Công cụ chọn màu có tính năng giữ tiêu điểm chính xác
  • 🛑 Không thông báo về các thay đổi, lỗi và thông báo
  • 🛑 Chế độ HighContrast chưa được bật

11. Thông báo về các thay đổi với Phát thanh viên trực tiếp

Bạn cần thông báo cho trình đọc màn hình khi có nội dung nào đó trên trang thay đổi. Hãy tưởng tượng bạn đang cố gắng gửi biểu mẫu hoặc hoàn tất giao dịch mua nhưng không biết rằng một lỗi đã xuất hiện khiến bạn không gửi được biểu mẫu. Thật khó chịu!

LiveAnnouncer được dùng để thông báo tin nhắn cho người dùng trình đọc màn hình bằng cách sử dụng vùng aria-live để đảm bảo trình đọc màn hình được thông báo về thông báo và các thay đổi trực tiếp trên trang. Để biết thêm thông tin về vùng aria-live, hãy xem WAI-ARIA của W3C. Trong Angular, việc gọi LiveAnnouncer dưới dạng dịch vụ là một giải pháp có thể kiểm thử hơn so với các thuộc tính aria-live.

Khi kết thúc phần này, ứng dụng của bạn sẽ vượt qua quy trình kiểm tra sau:

  • 🛑 Không thông báo về các thay đổi, lỗi và thông báo

Bạn có thể xem các bước này trong phần bình luận: TODO: #11. Announce changes with LiveAnnouncer.

Xác định vấn đề

Để xác định vấn đề này, hãy bật trình đọc màn hình rồi chọn Mua mà không điền vào các trường biểu mẫu:

  1. Bật VoiceOver.
  2. Sử dụng thanh điều hướng thẻ để thay đổi màu và thực hiện giao dịch mua giả.
  3. Lưu ý rằng không có chỉ báo nào cho biết màu đã được chọn khi thoát khỏi hộp thoại và giao dịch mua không được đọc.

Trang web của cửa hàng Dumpling Time có giao diện hồng và đỏ với hộp thoại đang mở để chọn màu gói bánh bao

Thêm LiveAnnouncer vào mã

Thêm LiveAnnouncer và thông báo cả lựa chọn màu và giao dịch mua giả mạo dưới dạng chuỗi. Trong khi triển khai thực tế, thông tin này có thể được đọc khi bạn chuyển đến một hệ thống thanh toán của bên thứ ba hoặc khi gặp lỗi biểu mẫu.

  1. Thêm thông báo khi người dùng chọn một màu:

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. Thêm thông báo khi thực hiện giao dịch mua giả mạo:

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);
  }
}

Xác minh thay đổi

Bật lại trình đọc màn hình và xác minh nội dung thay đổi. Bạn hiện đã nhận được thông báo về lỗi!

Kiểm tra khả năng hỗ trợ tiếp cận:

  • Tất cả các trang đều có tiêu đề riêng biệt
  • Màu sắc có tỷ lệ tương phản đủ
  • HTML có ngữ nghĩa đảm bảo tương tác hợp lý
  • Trình đọc màn hình có thể truy cập vào tất cả các chế độ điều khiển
  • Thanh trượt sử dụng các thuộc tính ARIA để cung cấp nhãn
  • Công cụ chọn màu có tính năng bẫy lấy nét chính xác
  • Thông báo về những thay đổi, lỗi và thông báo
  • 🛑 Chế độ Tương phản cao chưa bật

12. Bật chế độ HighContrast

Microsoft Windows hỗ trợ một tính năng hỗ trợ tiếp cận có tên là Chế độ tương phản cao. Chế độ này thay đổi giao diện của tất cả ứng dụng, bao gồm cả ứng dụng web, để tăng độ tương phản một cách đáng kể. Trong Angular, bạn muốn tôn trọng lựa chọn ưu tiên của người dùng trong ứng dụng của mình.

HighContrastModeDetector cho phép bạn xác định xem trình duyệt hiện có ở môi trường chế độ tương phản cao hay không.

Internet Explorer, Microsoft Edge và Firefox hỗ trợ chế độ này. Google Chrome không hỗ trợ Chế độ tương phản cao của Windows. Dịch vụ này không phát hiện chế độ tương phản cao do tiện ích Tương phản cao của Chrome thêm vào.

Khi kết thúc phần này, ứng dụng của bạn sẽ vượt qua quy trình kiểm tra sau:

  • 🛑 Chế độ HighContrast chưa được bật

Bạn có thể tìm thấy các bước này trong phần bình luận: TODO: #12. Enable HighContrast mode.

Xác định vấn đề

Để xác định sự cố này, hãy mở ứng dụng của bạn trong Internet Explorer, Microsoft Edge hoặc Firefox, bật Chế độ tương phản cao và quan sát thấy không có thay đổi nào:

  1. Mở ứng dụng trong Internet Explorer, Microsoft Edge hoặc Firefox.
  2. Bật Chế độ tương phản cao.
  3. Lưu ý rằng ứng dụng không thay đổi.

Thêm tính năng hỗ trợ cho chế độ tương phản cao

Trong styles.scss, hãy sử dụng mixin cdk-high-contrast được cung cấp trong @angular/cdk/a11y để thêm đường viền vào các nút của bạn ở chế độ Độ tương phản cao:

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);
    }
  }
}

Xác minh các thay đổi

Làm mới ứng dụng và xác minh các thay đổi. Bạn đã thêm đường viền vào nút ở chế độ Tương phản cao!

Trang web của cửa hàng Dumpling Time có giao diện màu đỏ và hồng, đang bật Chế độ tương phản cao và nút mua hàng hiện được làm nổi bật bằng đường viền màu đỏ đậm Trang web của cửa hàng Dumpling Time có giao diện màu xanh dương và xanh lục, đang bật Chế độ tương phản cao và nút mua hàng hiện được làm nổi bật bằng đường viền màu xanh dương đậm

Kiểm tra khả năng hỗ trợ tiếp cận:

  • Tất cả các trang đều có tiêu đề riêng biệt
  • Màu sắc có tỷ lệ tương phản đủ
  • HTML có ngữ nghĩa đảm bảo tương tác hợp lý
  • Trình đọc màn hình có thể truy cập vào tất cả các chế độ điều khiển
  • Thanh trượt sử dụng các thuộc tính ARIA để cung cấp nhãn
  • Công cụ chọn màu có tính năng bẫy lấy nét chính xác
  • Thông báo về các thay đổi, lỗi và thông báo
  • Chế độ tương phản cao đang bật

13. Xin chúc mừng!

Xin chúc mừng! Bạn đã giải quyết các vấn đề thường gặp về hỗ trợ tiếp cận trên web trong ứng dụng Angular! 🎉

Để xem tất cả các giải pháp, hãy xem nhánh main.

Trang web của cửa hàng Dumpling Time có giao diện màu đỏ và hồng cho thấy tất cả thay đổi được thực hiện trong lớp học lập trình này Trang web của cửa hàng Dumpling Time có giao diện màu xanh dương và xanh lục cho thấy tất cả thay đổi được thực hiện trong lớp học lập trình này Kiểm tra Lighthouse của Chrome cho nhà phát triển với điểm số 100/100

Giờ đây, bạn đã biết các bước chính cần thiết để giải quyết 8 lỗi thường gặp về a11y trong ứng dụng Angular.

Tìm hiểu thêm

Hãy tham khảo các lớp học lập trình sau:

Đọc các tài liệu sau: