Giới thiệu về Cây hỗ trợ tiếp cận
Hãy tưởng tượng rằng bạn đang xây dựng một giao diện người dùng chỉ dành cho người dùng trình đọc màn hình. Ở đây, bạn không cần tạo giao diện người dùng trực quan nào, mà chỉ cần cung cấp đủ thông tin để trình đọc màn hình sử dụng.
Những gì bạn sẽ tạo là một loại API mô tả cấu trúc trang, tương tự như API DOM, nhưng bạn có thể nhận được ít thông tin hơn và ít nút hơn, vì nhiều thông tin đó chỉ hữu ích cho việc trình bày trực quan. Mã sẽ có dạng như sau.
![bản minh hoạ DOM API của trình đọc màn hình](https://web.dev/static/articles/the-accessibility-tree/image/screen-reader-dom-api-moc-86f15b848dd25.jpg?authuser=5&hl=vi)
Về cơ bản, đây là những gì trình duyệt thực sự hiển thị cho trình đọc màn hình. Trình duyệt sẽ lấy cây DOM và sửa đổi cây này thành một dạng hữu ích cho công nghệ hỗ trợ. Chúng tôi gọi cây đã sửa đổi này là Cây hỗ trợ tiếp cận.
Bạn có thể hình dung cây hỗ trợ tiếp cận trông giống một trang web cũ từ thập niên 90: một số hình ảnh, nhiều đường liên kết, có thể là một trường và một nút.
![trang web kiểu những năm 1990](https://web.dev/static/articles/the-accessibility-tree/image/a-1990s-style-web-page-71a74592e602e.png?authuser=5&hl=vi)
Việc quét một trang theo cách trực quan như trường hợp này sẽ mang lại cho bạn trải nghiệm tương tự như những gì người dùng trình đọc màn hình sẽ nhận được. Có giao diện nhưng đơn giản và trực tiếp, giống như giao diện cây hỗ trợ tiếp cận.
Cây hỗ trợ tiếp cận là nơi mà hầu hết các công nghệ hỗ trợ đều tương tác. Luồng diễn ra như thế này.
- Một ứng dụng (trình duyệt hoặc ứng dụng khác) hiển thị phiên bản ngữ nghĩa của giao diện người dùng với công nghệ hỗ trợ thông qua API.
- Công nghệ hỗ trợ có thể sử dụng thông tin đọc được thông qua API để tạo bản trình bày giao diện người dùng thay thế cho người dùng. Ví dụ: trình đọc màn hình sẽ tạo một giao diện trong đó người dùng sẽ nghe thấy nội dung trình bày bằng giọng nói về ứng dụng.
- Công nghệ hỗ trợ cũng có thể cho phép người dùng tương tác với ứng dụng theo cách khác. Ví dụ: hầu hết các trình đọc màn hình đều cung cấp móc để cho phép người dùng dễ dàng mô phỏng một thao tác nhấp chuột hoặc nhấn ngón tay.
- Công nghệ hỗ trợ sẽ chuyển tiếp ý định của người dùng (chẳng hạn như "nhấp") trở lại ứng dụng thông qua API hỗ trợ tiếp cận. Sau đó, ứng dụng có trách nhiệm diễn giải hành động đó một cách phù hợp trong bối cảnh giao diện người dùng ban đầu.
Đối với trình duyệt web, có thêm một bước ở mỗi hướng, vì thực tế, trình duyệt là một nền tảng cho các ứng dụng web chạy trong đó. Vì vậy, trình duyệt cần dịch ứng dụng web thành cây hỗ trợ tiếp cận và phải đảm bảo rằng các sự kiện thích hợp sẽ được kích hoạt trong JavaScript dựa trên thao tác của người dùng đến từ công nghệ hỗ trợ.
Nhưng đó là tất cả trách nhiệm của trình duyệt. Công việc của nhà phát triển web của chúng tôi chỉ là nhận thức được điều này và phát triển các trang web tận dụng được quy trình này để tạo ra trải nghiệm dễ tiếp cận cho người dùng.
Chúng tôi làm điều này bằng cách đảm bảo thể hiện chính xác ngữ nghĩa của các trang: đảm bảo rằng các phần tử quan trọng trong trang có vai trò, trạng thái và thuộc tính chính xác, đồng thời chúng tôi chỉ định tên và nội dung mô tả hỗ trợ tiếp cận. Sau đó, trình duyệt có thể cho phép công nghệ hỗ trợ truy cập vào thông tin đó để tạo ra trải nghiệm tuỳ chỉnh.
Ngữ nghĩa trong HTML gốc
Một trình duyệt có thể chuyển đổi cây DOM thành cây hỗ trợ tiếp cận vì phần lớn DOM có ý nghĩa ngữ nghĩa ngầm ẩn. Điều này có nghĩa là DOM sử dụng các phần tử HTML gốc mà trình duyệt nhận dạng được và hoạt động dự đoán được trên nhiều nền tảng. Khả năng hỗ trợ tiếp cận đối với các phần tử HTML gốc như đường liên kết hoặc nút sẽ được xử lý tự động. Chúng tôi có thể tận dụng khả năng hỗ trợ tiếp cận tích hợp sẵn đó bằng cách viết HTML thể hiện ngữ nghĩa của các phần tử trang.
Tuy nhiên, đôi khi chúng tôi sử dụng các phần tử giống như phần tử gốc nhưng không phải. Ví dụ: "nút" này hoàn toàn không phải là một nút.
Mã này có thể được tạo trong HTML theo nhiều cách; như sau đây là một cách.
<div class="button-ish">Give me tacos</div>
Khi chúng tôi không sử dụng một phần tử nút thực tế, trình đọc màn hình sẽ không biết được nội dung nào đã được đặt trên đó. Ngoài ra, chúng tôi sẽ phải thực hiện thêm việc thêm chỉ mục thẻ để những người dùng chỉ sử dụng bàn phím có thể sử dụng tính năng này vì hiện tại mã được mã hoá nên bạn chỉ có thể dùng chuột.
Chúng ta có thể dễ dàng khắc phục vấn đề này bằng cách sử dụng phần tử button
thông thường thay vì div
.
Việc sử dụng phần tử gốc cũng giúp chúng tôi xử lý các hoạt động tương tác với bàn phím. Và nhớ rằng bạn không phải mất các hiệu ứng hình ảnh bắt mắt chỉ vì sử dụng phần tử gốc; bạn có thể tạo kiểu cho các phần tử gốc để chúng trông theo cách bạn muốn mà vẫn giữ lại được hành vi và ngữ nghĩa ngầm ẩn.
Trước đó, chúng ta đã lưu ý rằng trình đọc màn hình sẽ thông báo vai trò, tên, trạng thái và giá trị của một phần tử. Bằng cách sử dụng đúng phần tử ngữ nghĩa, vai trò, trạng thái và giá trị được đề cập, nhưng chúng ta cũng phải đảm bảo rằng chúng ta có thể tìm thấy tên của một phần tử.
Nói chung, có hai loại tên:
- Nhãn hiển thị, được tất cả người dùng sử dụng để liên kết ý nghĩa với một phần tử, và
- Các phương án thay thế văn bản, chỉ được dùng khi không cần nhãn trực quan.
Đối với các phần tử cấp văn bản, chúng ta không cần làm gì vì theo định nghĩa, các phần tử này sẽ có một số nội dung văn bản. Tuy nhiên, đối với các phần tử đầu vào hoặc điều khiển và nội dung hình ảnh như hình ảnh, chúng ta cần đảm bảo chỉ định tên. Trên thực tế, việc cung cấp các lựa chọn thay thế văn bản cho mọi nội dung không phải văn bản là mục đầu tiên trong danh sách kiểm tra WebAIM.
Một cách để làm việc đó là làm theo đề xuất của họ rằng "Dữ liệu đầu vào biểu mẫu có nhãn văn bản được liên kết". Có 2 cách để liên kết nhãn với một phần tử biểu mẫu, chẳng hạn như hộp đánh dấu. Một trong hai phương thức này đều khiến văn bản nhãn trở thành mục tiêu nhấp cho hộp đánh dấu, điều này cũng hữu ích cho người dùng chuột hoặc màn hình cảm ứng. Để liên kết nhãn với một phần tử, hãy
- Đặt phần tử đầu vào bên trong phần tử nhãn
<label> <input type="checkbox">Receive promotional offers? </label>
hoặc
- Sử dụng thuộc tính
for
của nhãn và tham chiếu đếnid
của phần tử
<input id="promo" type="checkbox">
<label for="promo">Receive promotional offers?</label>
Khi hộp đánh dấu đã được gắn nhãn đúng cách, trình đọc màn hình có thể báo cáo rằng phần tử có vai trò là hộp đánh dấu, ở trạng thái đã đánh dấu và có tên là "Nhận ưu đãi khuyến mãi?".
![văn bản đầu ra trên màn hình từ VoiceOver hiển thị nhãn được đọc cho một hộp đánh dấu](https://web.dev/static/articles/the-accessibility-tree/image/on-screen-text-output-vo-2bf0c33d65f23.png?authuser=5&hl=vi)