Bài 7 · Vận dụng · 20 phút
a11y: web cho mọi người
Biên soạn bởi Nguyễn Anh Tuấn
Accessibility (a11y) - khả năng tiếp cận: HTML cho người dùng screen reader, bàn phím và thị lực kém; alt, label, ARIA, focus và tương phản màu theo WCAG.
Ngoài đời, một toà nhà tử tế có đường dốc cho xe lăn, thang máy có nút chữ nổi, vỉa hè có vạch gồ cho người khiếm thị. Những thứ đó không làm phiền ai, mà giúp nhiều người hơn dùng được toà nhà. Web cũng vậy - và việc làm cho trang ai cũng dùng được gọi là accessibility (khả năng tiếp cận), viết tắt a11y (chữ a, 11 chữ ở giữa, chữ y).
Ai cần a11y? Nhiều hơn ta tưởng:
- ▸Người khiếm thị dùng screen reader (phần mềm đọc màn hình) để NGHE trang thay vì nhìn.
- ▸Người chỉ dùng được bàn phím (không dùng chuột vì lý do vận động).
- ▸Người thị lực kém hoặc mù màu cần chữ đủ rõ, đủ tương phản.
- ▸Cả người bình thường lúc bất tiện: đang bế mèo nên dùng một tay, hay nhìn màn hình ngoài nắng chói.
Điều cốt lõi
Người khiếm thị không nhìn trang mà nghe nó, qua screen reader. Phần mềm này đọc nội dung tuần tự, đọc alt của ảnh, đọc tên trường form - và quan trọng: cho người dùng nhảy nhanh giữa các heading và landmark, đúng như cấu trúc mèo con dựng ở bài Cấu trúc một trang chuẩn semantic.
Nghĩa là phần lớn a11y mèo con đã làm rồi mà không hay: thẻ semantic cho landmark, heading có thứ bậc, và đặc biệt thuộc tính alt - thứ âm thầm phục vụ cả người khiếm thị lẫn máy tìm kiếm:
Một điểm mới đáng nhớ: hãy dùng đúng thẻ cho đúng việc. Một nút bấm phải là <button>, không phải một <div> trang điểm cho giống nút. Vì screen reader đọc thẻ button là "nút bấm" và cho bấm được; còn div thì với nó chỉ là một ô vô nghĩa.
nut.html · đúng thẻ thì máy đọc hiểu ngay (mở .html bằng trình duyệt)
<!-- Tốt: máy đọc biết đây là nút, bấm được bằng bàn phím -->
<button>Mua ngay</button>
<!-- Tệ: nhìn giống nút nhưng máy đọc không hiểu, không bấm được bằng bàn phím -->
<div class="btn">Mua ngay</div> - ▸Screen reader đọc trang tuần tự và nhảy theo heading/landmark - cấu trúc semantic là bản đồ.
- ▸alt, label, heading mèo con đã học chính là nền a11y, không cần làm lại.
- ▸Dùng đúng thẻ (button cho nút, a cho link) để máy đọc hiểu và bàn phím dùng được.
Trung thực
Nhiều người duyệt web chỉ bằng bàn phím: phím Tab nhảy tới phần tử tương tác kế tiếp, Shift+Tab lùi lại, Enter/Space để kích hoạt. Một trang tốt phải đi được hết bằng bàn phím. Có hai thói quen giữ điều đó.
Một: dùng thẻ tương tác đúng. Các thẻ a, button, input tự nhận được focus và bấm được bằng bàn phím - miễn phí. Còn div/span thì không, dù mèo con tô cho nó giống nút đến đâu.
Hai: đừng xoá focus ring - vòng sáng trình duyệt vẽ quanh phần tử đang được chọn. Với người dùng bàn phím, nó chính là "con trỏ chuột" của họ: xoá đi là họ lạc, không biết mình đang ở đâu trên trang. CSS outline: none để cho "đẹp" là một lỗi a11y kinh điển.
focus.html · thứ tự Tab đi theo thứ tự các thẻ trong trang
<a href="/">Trang chủ</a> <!-- Tab lần 1 dừng ở đây -->
<a href="/khoa-hoc">Khoá học</a> <!-- Tab lần 2 -->
<input id="q" /> <!-- Tab lần 3 -->
<button>Tìm</button> <!-- Tab lần 4 --> - ▸Tab/Shift+Tab di chuyển focus; Enter/Space kích hoạt - nhiều người duyệt web chỉ vậy.
- ▸a, button, input tự dùng được bằng bàn phím; div/span thì không.
- ▸Giữ focus ring (outline) - nó là con trỏ của người dùng bàn phím.
- ▸Thứ tự focus đi theo thứ tự thẻ trong HTML, nên trật tự thẻ hợp lý là quan trọng.
Đa số trường hợp, HTML semantic đã đủ kể cho máy đọc mọi thứ. Nhưng đôi khi có khoảng trống - vd một nút chỉ có icon, không có chữ. Mắt người nhìn dấu ✕ thì đoán ra "đóng", nhưng screen reader chẳng có chữ nào để đọc. Lúc đó ta cần ARIA (Accessible Rich Internet Applications) - bộ thuộc tính bổ nghĩa thêm cho máy đọc.
Hai thứ hay dùng nhất: aria-label đặt một cái tên cho phần tử không có chữ, và aria-hidden="true" giấu phần thuần trang trí khỏi máy đọc.
aria.html · đặt tên cho nút chỉ có icon
<!-- Nút icon: thêm aria-label để máy đọc biết nó là gì -->
<button aria-label="Đóng">✕</button>
<!-- Icon thuần trang trí: giấu khỏi máy đọc cho đỡ ồn -->
<span aria-hidden="true">★</span> Đánh giá cao Luật vàng của ARIA
Người thị lực kém, người mù màu, hay bất cứ ai đọc màn hình ngoài nắng đều cần chữ nổi đủ rõ trên nền. Để đo "đủ rõ" một cách khách quan, chuẩn WCAG (Web Content Accessibility Guidelines) dùng tỉ số tương phản (contrast ratio) giữa màu chữ và màu nền - từ 1:1 (trùng màu, vô hình) tới 21:1 (đen trên trắng). Ngưỡng tối thiểu cho chữ thường là 4.5:1 (mức AA).
Kéo thử hai màu dưới đây và xem tỉ số đổi thế nào - chú ý cặp xám-trên-trắng trượt sát ngưỡng:
Mèo con ham học
Đọc được dòng này dễ hay khó?
Một cái bẫy hay gặp: màu xám nhạt như #777 trên nền trắng nhìn "có vẻ ổn" nhưng chỉ đạt khoảng 4.48:1 - trượt AA trong gang tấc. Chữ đậm hơn một chút là qua.
Trung thực
- ▸Tỉ số tương phản đo chữ có nổi đủ trên nền không (1:1 vô hình → 21:1 đen/trắng).
- ▸Chữ thường cần >= 4.5:1 (WCAG AA); chữ lớn nhẹ ngưỡng hơn (3:1).
- ▸Đừng chỉ dùng màu để báo thông tin - kèm chữ/icon cho người mù màu.
Mèo con không cần công cụ đắt tiền để kiểm a11y cơ bản. Ba cách nhanh:
- ▸Cất chuột đi, đi hết trang chỉ bằng Tab - tới được mọi nút/link và luôn thấy focus ring?
- ▸Mở DevTools của trình duyệt, chạy Lighthouse (hoặc tiện ích axe) để nó chấm điểm a11y.
- ▸Đọc to alt của từng ảnh xem có hiểu ảnh nói gì không; thử phóng to chữ 200%.
Để ý điều này: gần như mọi việc làm cho a11y - HTML semantic, alt, heading có thứ bậc, link có chữ rõ nghĩa - cũng chính là việc làm cho SEO. Lý do giống hệt nhau: screen reader và Google đều là "máy đọc" trang qua thẻ chứ không qua mắt. Làm tốt cái này thường được luôn cái kia.
Bước tiếp theo
Câu hỏi thường gặp
a11y là cách viết tắt của "accessibility" (khả năng tiếp cận): chữ a, rồi 11 chữ cái ở giữa, rồi chữ y - nên thành a11y. Kiểu viết này giống i18n (internationalization) hay l10n (localization). Đọc là "a-eleven-y" hoặc cứ gọi "accessibility" cho rõ.
Phần lớn là không, nếu mèo con đã viết HTML semantic đúng từ các bài trước. Dùng đúng thẻ (button, nav, label, h1-h6), viết alt cho ảnh, gắn label cho input - bấy nhiêu đã lo phần lớn a11y. Phần thêm chỉ là vài điểm nhỏ: aria-label cho nút icon, giữ focus ring, và chọn màu đủ tương phản.
Là phần mềm đọc to nội dung màn hình cho người khiếm thị (vd NVDA trên Windows, VoiceOver trên máy Mac/iPhone). Nó đọc chữ, đọc alt của ảnh, đọc tên trường form, và cho người dùng nhảy nhanh giữa các heading và landmark - đúng như cấu trúc semantic mèo con đã dựng.
Không. Luật vàng là "không dùng ARIA còn hơn dùng ARIA sai": ưu tiên thẻ HTML đúng nghĩa trước, vì chúng đã mang sẵn ý nghĩa cho máy đọc. Ở mức nhập môn chỉ cần nhớ hai thứ hay dùng: aria-label (đặt tên cho phần tử không có chữ, như nút icon) và aria-hidden (giấu phần trang trí khỏi máy đọc).
Tick những điều em tự tin làm được. Càng lên cao, em càng hiểu sâu.
Trả lời vài câu để chắc rằng em đã nắm bài.
a11y là cách viết tắt của từ nào?
- 1
Nút thật, không phải div
Cho một "nút" được làm bằng <div class="btn">Mua</div>. Viết lại cho đúng để nó focus và bấm được bằng bàn phím.
✅ Hoàn thành khi: Dùng <button>Mua</button> (hoặc <a> nếu là điều hướng) thay cho div - tự nhận focus và kích hoạt bằng Enter/Space.
- 2
Đặt tên cho nút icon
Một nút đóng chỉ có dấu ✕ bên trong, không có chữ. Thêm thứ để screen reader đọc được nó là nút gì.
✅ Hoàn thành khi: Nút có aria-label="Đóng" (hoặc tên rõ nghĩa tương đương) bọc quanh dấu ✕.
- 3
alt cho hai loại ảnh
Với mỗi ảnh, viết thuộc tính alt: (a) ảnh chân dung tác giả bài viết; (b) một icon trang trí hình ngôi sao thuần thẩm mỹ.
✅ Hoàn thành khi: (a) alt mô tả nội dung (vd "Chân dung tác giả Mèo Con"); (b) alt="" rỗng vì chỉ trang trí, để máy đọc bỏ qua.
- 4
Đừng giấu con trỏ bàn phím
Một bạn viết CSS "outline: none" cho mọi nút để cho "đẹp". Giải thích vì sao điều này hại người dùng bàn phím.
✅ Hoàn thành khi: Nêu: outline là focus ring - dấu hiệu phần tử nào đang được chọn; xoá đi thì người dùng bàn phím lạc, không biết đang ở đâu.
- 5
Soi độ tương phản
Dùng widget trong bài: đặt màu chữ #777777 trên nền trắng #ffffff. Ghi lại tỉ số và cho biết nó đạt chuẩn AA chữ thường không.
✅ Hoàn thành khi: Tỉ số khoảng 4.48:1; KHÔNG đạt AA chữ thường (cần >= 4.5:1) - sửa cho chữ đậm hơn để vượt ngưỡng.
- 6
Đi hết trang bằng bàn phím
Mở một trang bất kỳ mèo con đã làm, cất chuột đi. Chỉ dùng phím Tab (và Shift+Tab) đi qua mọi link/nút/ô nhập.
✅ Hoàn thành khi: Tới được mọi phần tử tương tác theo thứ tự hợp lý, và luôn nhìn thấy phần tử nào đang được chọn (có focus ring).