Sử dụng chỉ mục thẻ

Dave Gash
Dave Gash
Meggin Kearney
Meggin Kearney
Alexandra Klepper
Alexandra Klepper

Trình tự thẻ mặc định do vị trí DOM của các phần tử HTML ngữ nghĩa cung cấp rất thuận tiện, nhưng đôi khi bạn có thể cần sửa đổi trình tự thẻ. Lý tưởng nhất là di chuyển các phần tử trong HTML, nhưng có thể không khả thi. Trong những trường hợp này, bạn có thể sử dụng thuộc tính HTML tabindex để đặt rõ vị trí thẻ của một phần tử.

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.5.
  • Safari: 3.1.

Nguồn

Bạn có thể áp dụng tabindex cho bất kỳ phần tử nào, mặc dù không nhất thiết phải hữu ích trên mọi phần tử và lấy một dải giá trị số nguyên. Với tabindex, bạn có thể chỉ định thứ tự rõ ràng cho các phần tử trang có thể lấy tiêu điểm, chèn một phần tử không thể lấy tiêu điểm vào thứ tự thẻ và xoá các phần tử khỏi thứ tự thẻ. Ví dụ:

tabindex="0": Chèn một phần tử vào thứ tự thẻ tự nhiên. Bạn có thể đặt tiêu điểm vào phần tử bằng cách nhấn phím Tab và có thể đặt tiêu điểm vào phần tử bằng cách gọi phương thức focus() của phần tử đó.

tabindex="-1": Xoá một phần tử khỏi thứ tự thẻ thông thường, nhưng bạn vẫn có thể lấy tiêu điểm phần tử đó bằng cách gọi phương thức focus().

tabindex="5": Bất kỳ chỉ mục thẻ nào lớn hơn 0 sẽ đưa phần tử đó lên trước thứ tự thẻ thông thường. Nếu có nhiều phần tử có tabindex lớn hơn 0, thì thứ tự thẻ bắt đầu từ giá trị thấp nhất lớn hơn 0 và tăng dần.

Điều này đặc biệt đúng đối với các phần tử không đầu vào như tiêu đề, hình ảnh hoặc tiêu đề bài viết. Nếu có thể, tốt nhất bạn nên sắp xếp mã nguồn để trình tự DOM cung cấp thứ tự thẻ hợp lý. Nếu bạn sử dụng tabindex, hãy hạn chế thành phần này ở các thành phần điều khiển tương tác tuỳ chỉnh như nút, thẻ, trình đơn thả xuống và trường văn bản; tức là các phần tử mà người dùng có thể dự kiến sẽ cung cấp dữ liệu đầu vào.

Chỉ thêm tabindex vào nội dung có tính tương tác. Ngay cả khi nội dung quan trọng, chẳng hạn như hình ảnh chính, người dùng trình đọc màn hình vẫn có thể hiểu được nội dung đó mà không cần thêm tiêu điểm.

Quản lý tiêu điểm ở cấp trang

Đôi khi, tabindex là cần thiết để mang lại trải nghiệm liền mạch cho người dùng. Ví dụ: nếu bạn tạo một trang mạnh mẽ với nhiều phần nội dung, trong đó không phải tất cả nội dung đều hiển thị cùng lúc. Tức là đường liên kết điều hướng sẽ thay đổi nội dung hiển thị mà không cần làm mới trang.

Trong trường hợp này, hãy xác định vùng nội dung đã chọn và cung cấp cho vùng nội dung đó một tabindex của -1 rồi gọi phương thức focus. Điều này đảm bảo nội dung không xuất hiện theo thứ tự thẻ tự nhiên. Kỹ thuật này, được gọi là quản lý tiêu điểm, giúp đồng bộ hoá ngữ cảnh mà người dùng nhận thấy với nội dung hình ảnh của trang web.

Quản lý tiêu điểm trong các thành phần

Trong một số trường hợp, bạn cũng phải quản lý tiêu điểm ở cấp điều khiển, chẳng hạn như với các thành phần tuỳ chỉnh.

Ví dụ: phần tử select có thể nhận tiêu điểm cơ bản. Tuy nhiên, sau khi lấy tiêu điểm ở đó, bạn có thể dùng các phím mũi tên để hiện thêm các tuỳ chọn có thể chọn. Nếu bạn tạo một phần tử select tuỳ chỉnh, điều quan trọng là phải mô phỏng hành vi đó để người dùng bàn phím vẫn có thể tương tác với thành phần điều khiển của bạn.

Bạn có thể gặp khó khăn khi biết được hành vi nào của bàn phím cần triển khai. Hướng dẫn Thực hành soạn thảo ứng dụng Internet đa dạng thức có thể truy cập (ARIA) liệt kê các loại thành phần và những loại thao tác trên bàn phím mà những thành phần đó hỗ trợ.

Có thể bạn đang làm việc với Thành phần tuỳ chỉnh giống như một nhóm nút chọn, nhưng có giao diện và hành vi riêng.

<radio-group>
    <radio-button>Water</radio-button>
    <radio-button>Coffee</radio-button>
    <radio-button>Tea</radio-button>
    <radio-button>Cola</radio-button>
    <radio-button>Ginger Ale</radio-button>
</radio-group>

Để xác định loại hỗ trợ bàn phím mà họ cần, hãy xem Hướng dẫn về các phương pháp biên soạn ARIA. Phần 2 chứa danh sách các mẫu thiết kế, bao gồm cả bảng đặc điểm cho các nhóm nút chọn, thành phần hiện có khớp nhất với phần tử mới của bạn.

Một trong những hành vi phổ biến trên bàn phím cần được hỗ trợ là các phím mũi tên lên/xuống/trái/phải. Để thêm hành vi này vào thành phần mới, chúng ta sử dụng một kỹ thuật có tên là tabindex di chuyển.

Tabindex di chuyển hoạt động bằng cách đặt tabindex thành -1 cho tất cả các thành phần con ngoại trừ thành phần con đang hoạt động.

<radio-group>
  <radio-button tabindex="0">Water</radio-button>
  <radio-button tabindex="-1">Coffee</radio-button>
  <radio-button tabindex="-1">Tea</radio-button>
  <radio-button tabindex="-1">Cola</radio-button>
  <radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>

Thành phần này sử dụng trình nghe sự kiện bàn phím để xác định phím mà người dùng nhấn; khi điều này xảy ra, thành phần này sẽ đặt tabindex của thành phần con được lấy tiêu điểm trước đó thành -1, đặt tabindex của thành phần con sẽ được lấy tiêu điểm thành 0 và gọi phương thức lấy tiêu điểm trên thành phần đó.

<radio-group>
    <!-- Assuming the user pressed the down arrow, we'll focus the next available child -->
    <radio-button tabindex="-1">Water</radio-button>
    <radio-button tabindex="0">Coffee</radio-button> // call .focus() on this element
    <radio-button tabindex="-1">Tea</radio-button>
    <radio-button tabindex="-1">Cola</radio-button>
    <radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>

Khi người dùng đến phần tử con cuối cùng (hoặc đầu tiên, tuỳ thuộc vào hướng họ di chuyển tiêu điểm), tiêu điểm sẽ lặp lại phần tử con đầu tiên (hoặc cuối cùng).

Hãy thử ví dụ sau. Kiểm tra phần tử trong DevTools để quan sát chỉ mục thẻ chuyển từ đài phát này sang đài phát tiếp theo.

Cửa sổ bật lên và bẫy bàn phím

Tốt nhất là bạn nên tránh quản lý tiêu điểm theo cách thủ công vì việc này có thể dẫn đến các tình huống phức tạp. Ví dụ: một tiện ích tự động hoàn thành cố gắng quản lý tiêu điểm và ghi lại hành vi của thẻ, nhưng ngăn người dùng rời khỏi thẻ cho đến khi hoàn tất. Đây được gọi là bẫy bàn phím và có thể gây khó chịu cho người dùng.

Mục 2.1.2 của WCAG nêu rõ rằng tiêu điểm của bàn phím không được bị khoá hoặc bị giữ ở một phần tử trang cụ thể. Người dùng phải có thể di chuyển đến và đi từ tất cả các thành phần trên trang chỉ bằng bàn phím.

Trường hợp ngoại lệ của quy tắc này là phương thức. Tuy nhiên, bạn vẫn nên tránh sử dụng tabindex khi tạo một cửa sổ bật lên. Với inert, bạn có thể đảm bảo rằng người dùng không thể vô tình tương tác với một phần tử (một bẫy bàn phím có chủ ý). Sử dụng phần tử <dialog> (theo mặc định là không hoạt động) để tạo một cửa sổ bật lên cho người dùng trong khi chặn các lượt nhấp và thẻ bên ngoài cửa sổ bật lên. Điều này cho phép người dùng tập trung vào một lựa chọn bắt buộc.