Developer Tools

Khả năng tiếp cận web (a11y): Hướng dẫn thực tiễn cho lập trình viên

Tìm hiểu các nguyên tắc khả năng tiếp cận thiết yếu, thuộc tính ARIA, mẫu điều hướng bằng bàn phím và các công cụ kiểm thử giúp ứng dụng web của bạn dễ dùng với mọi người.

8 phút đọc

Person using a laptop with assistive technology

Hơn 1,3 tỷ người — chiếm 16% dân số thế giới — sống chung với một dạng khuyết tật nào đó. Khả năng tiếp cận web đảm bảo rằng trang web của bạn hoạt động tốt với những người dùng phụ thuộc vào trình đọc màn hình, điều hướng bằng bàn phím, thiết bị truy cập chuyển đổi hoặc các công nghệ hỗ trợ khác. Ngoài việc đảm bảo tính bao hàm, các trang web có khả năng tiếp cận tốt còn được xếp hạng cao hơn trên công cụ tìm kiếm, hoạt động tốt hơn trên thiết bị di động và thường được yêu cầu bởi luật pháp.

Bốn nguyên tắc POUR

Hướng dẫn Khả năng tiếp cận Nội dung Web (WCAG) được xây dựng dựa trên bốn nguyên tắc cốt lõi. Nội dung phải:

  1. Perceivable (Có thể cảm nhận) — Thông tin phải được trình bày theo những cách người dùng có thể tiếp nhận (không chỉ qua thị giác).
  2. Operable (Có thể vận hành) — Tất cả chức năng phải có thể sử dụng bằng bàn phím.
  3. Understandable (Có thể hiểu được) — Nội dung và giao diện phải dễ hiểu.
  4. Robust (Bền vững) — Nội dung phải được các công nghệ hỗ trợ phân tích được.

WCAG 2.2 định nghĩa ba cấp độ tuân thủ:

  • A — Tối thiểu (bắt buộc phải có)
  • AA — Mục tiêu tiêu chuẩn cho hầu hết các tổ chức
  • AAA — Tối đa (mục tiêu hướng đến cho một số nội dung)

Hầu hết các yêu cầu pháp lý (ADA, EN 301 549, EAA) đều đòi hỏi tuân thủ cấp AA.

Ưu tiên HTML ngữ nghĩa

Điều có tác động lớn nhất bạn có thể làm cho khả năng tiếp cận là sử dụng đúng phần tử HTML cho đúng mục đích. Trình duyệt và trình đọc màn hình đã biết cách xử lý các phần tử ngữ nghĩa:

<!-- ❌ Div soup — không có ngữ nghĩa -->
<div class="header">
  <div class="nav">
    <div class="nav-item" onclick="navigate()">Home</div>
  </div>
</div>

<!-- ✅ HTML ngữ nghĩa — trình đọc màn hình hiểu được -->
<header>
  <nav>
    <a href="/">Home</a>
  </nav>
</header>

Các phần tử ngữ nghĩa quan trọng và vai trò của chúng:

Phần tử Vai trò
<header>, <footer> Vùng mốc trang
<nav> Mốc điều hướng
<main> Nội dung chính (một phần tử mỗi trang)
<aside> Nội dung bổ sung
<h1><h6> Cấu trúc tiêu đề
<button> Điều khiển tương tác
<a href> Liên kết điều hướng
<label> Nhãn trường biểu mẫu
<table> Dữ liệu dạng bảng

Hình ảnh và văn bản thay thế (alt text)

Mỗi hình ảnh có ý nghĩa đều cần thuộc tính alt mô tả nội dung của nó. Hình ảnh trang trí được gán alt="" rỗng để trình đọc màn hình bỏ qua:

<!-- Hình ảnh có ý nghĩa -->
<img src="chart.png" alt="Biểu đồ cột cho thấy doanh thu tăng 40% trong Q1 2026">

<!-- Hình ảnh trang trí -->
<img src="divider.svg" alt="">

<!-- Nút biểu tượng — mô tả hành động, không phải biểu tượng -->
<button>
  <img src="trash.svg" alt="Xóa mục">
</button>

<!-- Tránh: "image of" (hình ảnh của) dư thừa -->
<!-- ❌ --> <img src="cat.jpg" alt="Image of a cat">
<!-- ✅ --> <img src="cat.jpg" alt="Orange tabby cat sitting on a windowsill">

Độ tương phản màu sắc

Người dùng có thị lực kém hoặc mù màu phụ thuộc vào độ tương phản đủ giữa văn bản và nền.

Yêu cầu WCAG AA:

  • Văn bản thường (< 18pt): tỷ lệ tương phản tối thiểu 4.5:1
  • Văn bản lớn (≥ 18pt hoặc 14pt đậm): tỷ lệ tương phản tối thiểu 3:1
  • Thành phần UI và đối tượng đồ họa: tối thiểu 3:1

Không chỉ dựa vào màu sắc để truyền tải thông tin:

<!-- ❌ Chỉ dùng màu để chỉ trạng thái -->
<span class="text-red-500">Error</span>

<!-- ✅ Màu sắc + biểu tượng + văn bản -->
<span class="text-red-500 flex items-center gap-1">
  <svg aria-hidden="true"><!-- error icon --></svg>
  Error: Invalid email address
</span>

Biểu mẫu: nhãn, lỗi và mô tả

Mỗi điều khiển trong biểu mẫu cần có một nhãn hiển thị và được liên kết đúng cách:

<!-- ✅ Liên kết nhãn rõ ràng -->
<label for="email">Email address</label>
<input id="email" type="email" aria-describedby="email-hint email-error">
<p id="email-hint" class="text-sm text-gray-500">We'll never share your email.</p>
<p id="email-error" role="alert" class="text-sm text-red-600" hidden>
  Please enter a valid email address.
</p>

Các mẫu khả năng tiếp cận quan trọng trong biểu mẫu:

  • Dùng for/id để liên kết nhãn với trường nhập liệu
  • Dùng aria-describedby cho văn bản gợi ý và thông báo lỗi
  • Dùng role="alert" hoặc aria-live="polite" cho thông báo lỗi động
  • Dùng aria-required="true" hoặc thuộc tính required gốc
  • Nhóm các trường liên quan bằng <fieldset><legend>

Điều hướng bằng bàn phím

Tất cả các phần tử tương tác phải có thể truy cập và vận hành bằng bàn phím:

  • Tab — di chuyển tiến qua các phần tử có thể được focus
  • Shift+Tab — di chuyển lùi
  • Enter/Space — kích hoạt nút, hộp kiểm
  • Phím mũi tên — điều hướng trong các thành phần (menu, tab, thanh trượt)
  • Escape — đóng hộp thoại, ẩn dropdown

Chỉ báo focus phải hiển thị rõ ràng. Tuyệt đối không làm điều này mà không có phương án thay thế:

/* ❌ Ẩn hoàn toàn chỉ báo focus */
*:focus { outline: none; }

/* ✅ Kiểu focus tùy chỉnh vẫn hiển thị rõ ràng */
*:focus-visible {
  outline: 2px solid #3b82f6;
  outline-offset: 2px;
}

ARIA: khi nào và cách sử dụng

Các thuộc tính ARIA (Accessible Rich Internet Applications) bổ sung ý nghĩa ngữ nghĩa khi HTML đơn thuần không đủ. Quy tắc đầu tiên của ARIA: đừng dùng ARIA nếu HTML gốc có thể làm được việc đó.

<!-- Đặt nhãn cho phần tử không có nhãn hiển thị -->
<button aria-label="Close dialog">✕</button>

<!-- Mô tả trạng thái mở rộng -->
<button aria-expanded="false" aria-controls="menu">Menu</button>
<ul id="menu" hidden>...</ul>

<!-- Vùng trực tiếp cho nội dung động -->
<div aria-live="polite" aria-atomic="true">
  <!-- Trình đọc màn hình thông báo các thay đổi trong vùng này -->
  3 results found
</div>

<!-- Vai trò mốc khi không có phần tử ngữ nghĩa phù hợp -->
<div role="search">
  <input type="search" placeholder="Search...">
</div>

Quản lý focus cho SPA và hộp thoại modal

Trong các ứng dụng một trang (SPA), việc điều hướng trang không kích hoạt trình duyệt reset focus. Khi một "trang" được tải, hãy chuyển focus đến vị trí có ý nghĩa:

// Sau khi điều hướng, focus vào tiêu đề chính
document.querySelector("h1")?.focus();

Đối với hộp thoại modal:

  1. Khi modal mở, chuyển focus đến phần tử có thể focus đầu tiên bên trong
  2. Giữ focus trong modal khi nó đang mở (ngăn Tab chạm đến nội dung phía sau)
  3. Khi modal đóng, trả focus về phần tử đã kích hoạt nó

Kiểm thử khả năng tiếp cận

Công cụ tự động (phát hiện khoảng 30-40% vấn đề)

  • Tiện ích mở rộng trình duyệt axe DevTools
  • Kiểm tra khả năng tiếp cận Lighthouse trong Chrome DevTools
  • Tiện ích mở rộng trình duyệt WAVE

Kiểm thử thủ công (cần thiết để bao phủ toàn diện)

  1. Điều hướng chỉ bằng bàn phím — rút chuột ra và điều hướng toàn bộ trang web của bạn
  2. Kiểm thử trình đọc màn hình — NVDA + Firefox (Windows), VoiceOver + Safari (Mac/iOS)
  3. Phóng to 200% — đảm bảo không có nội dung bị mất hoặc chồng lên nhau
  4. Mô phỏng mù màu — DevTools trình duyệt → Rendering → Emulate vision deficiencies

Khả năng đọc

Ngôn ngữ đơn giản cải thiện khả năng tiếp cận cho người dùng có khuyết tật nhận thức. Dùng công cụ Readability Score của chúng tôi để kiểm tra trình độ đọc hiểu của nội dung — hướng tới Lớp 8-10 cho đối tượng đại chúng.

Những cải tiến nhanh bạn có thể làm ngay hôm nay

  1. Thêm văn bản alt cho tất cả hình ảnh
  2. Đảm bảo tất cả trường nhập liệu trong biểu mẫu đều có phần tử <label> liên kết
  3. Kiểm tra độ tương phản màu sắc đạt 4.5:1 cho văn bản thân bài
  4. Thêm kiểu :focus-visible và không bao giờ xóa outline mà không có phương án thay thế
  5. Dùng <button> cho hành động và <a href> cho điều hướng (không bao giờ ngược lại)
  6. Thêm lang="en" (hoặc ngôn ngữ phù hợp) vào phần tử <html> của bạn
  7. Dùng một <h1> mỗi trang và duy trì cấu trúc tiêu đề logic

Khả năng tiếp cận không phải là tính năng bổ sung — đó là một đặc tính chất lượng. Xây dựng sản phẩm có khả năng tiếp cận ngay từ đầu rẻ hơn nhiều so với việc cải tạo sau này, và nó giúp sản phẩm của bạn tốt hơn cho tất cả mọi người.