Tập trung

Theo mặc định, các phần tử tương tác (bao gồm cả thành phần điều khiển biểu mẫu, đường liên kết và nút) đều có thể lấy tiêu điểm và di chuyển bằng phím Tab. Các phần tử có thể nhấn phím Tab là một phần trong thứ tự điều hướng tiêu điểm tuần tự của tài liệu. Các phần tử khác ở trạng thái tĩnh, tức là không tương tác. Với các thuộc tính HTML, bạn có thể làm cho các phần tử tương tác trở nên trơ và làm cho các phần tử trơ trở nên tương tác.

Theo mặc định, thứ tự tiêu điểm điều hướng sẽ giống với thứ tự trực quan, tức là thứ tự mã nguồn. Có những thuộc tính HTML có thể thay đổi thứ tự này và các thuộc tính CSS có thể thay đổi thứ tự hiển thị của nội dung. Việc thay đổi thứ tự nhấn phím Tab bằng HTML hoặc thứ tự hiển thị trực quan bằng CSS có thể gây ảnh hưởng tiêu cực đến trải nghiệm người dùng.

Không được thay đổi thứ tự nhấn phím tab thực tế và cảm nhận bằng CSS và HTML. Như 2 ví dụ sau đây minh hoạ, thứ tự thẻ khác với thứ tự dự kiến về mặt hình ảnh sẽ gây nhầm lẫn cho người dùng và ảnh hưởng tiêu cực đến trải nghiệm người dùng.

Trong ví dụ này, giá trị của thuộc tính tabindex đã khiến thứ tự thẻ trở nên lộn xộn:

Trong ví dụ này, CSS đã tạo ra sự khác biệt giữa thứ tự nhấn phím Tab và thứ tự hiển thị của nội dung:

Khai báo flex-flow: row-reverse; đã đảo ngược thứ tự hiển thị. Ngoài ra, thuộc tính order của CSS đã được áp dụng cho từ thứ sáu là "This", giúp di chuyển từ đó một cách trực quan. Thứ tự nhấn phím tab là thứ tự của mã, không còn khớp với thứ tự trực quan, tạo ra sự gián đoạn cho người dùng bàn phím.

Tạo tính tương tác cho các phần tử không hoạt động

Các thuộc tính contenteditabletabindex (là các thuộc tính chung) có thể được thêm vào bất kỳ phần tử nào, giúp các phần tử đó có thể lấy tiêu điểm trong quá trình này. Bạn cũng có thể đặt tiêu điểm cho các phần tử có thể lấy tiêu điểm bằng chuột hoặc con trỏ, bằng cách đặt thuộc tính autofocus hoặc bằng tập lệnh, chẳng hạn như bằng element.focus().

Thuộc tính tabindex

Thuộc tính tabindex chung (được giới thiệu trong các thuộc tính) cho phép các phần tử không thể nhận tiêu điểm nhận được tiêu điểm, thường là bằng phím Tab, do đó có tên như vậy.

Thuộc tính tabindex lấy một số nguyên làm giá trị. Giá trị âm giúp một phần tử có thể lấy tiêu điểm nhưng không thể nhấn phím tab. Giá trị tabindex0 giúp phần tử có thể lấy tiêu điểm và có thể dùng phím Tab, thêm phần tử mà bạn áp dụng giá trị này vào thứ tự điều hướng tiêu điểm tuần tự theo thứ tự mã nguồn. Giá trị 1 trở lên khiến phần tử có thể lấy tiêu điểm và có thể dùng phím Tab, nhưng sẽ thêm phần tử đó vào một chuỗi thao tác bằng phím Tab được ưu tiên và bạn nên tránh dùng.

Trên trang này, nút chia sẻ <share-action> là một phần tử tuỳ chỉnh. tabindex="0" sẽ thêm phần tử không thể lấy tiêu điểm này vào thứ tự nhấn phím Tab mặc định của bàn phím:

<share-action authors="@front-end.social/@estellevw" data-action="click" data-category="web.dev" data-icon="share" data-label="share, mastodon" role="button" tabindex="0">
  <svg aria-label="share" role="img" xmlns="http://www.w3.org/2000/svg">
    <use href="#shareIcon" />
  </svg>
  <span>Share</span>
</share-action>

Có một phần tử tuỳ chỉnh khác trên trang này: thanh điều hướng cục bộ có một phần tử tuỳ chỉnh với giá trị tabindex âm:

<web-navigation-drawer type="standard" tabindex="-1">

Thuộc tính tabindex có giá trị âm giúp phần tử có thể lấy tiêu điểm nhưng không thể dùng phím Tab. Phần tử này có thể nhận tiêu điểm, chẳng hạn như sử dụng HTMLElement.focus(), nhưng không thuộc thứ tự điều hướng tiêu điểm tuần tự. Quy ước cho các phần tử không thể nhấn phím tab và có thể lấy tiêu điểm là sử dụng tabindex="-1". Nếu bạn thêm tabindex="-1" vào một phần tử tương tác, phần tử đó sẽ không còn được phép dùng phím Tab nữa.

Bạn có thể dùng phương thức element.focus() để đặt tiêu điểm cho các phần tử có thể lấy tiêu điểm. Trình duyệt cuộn các phần tử được lấy tiêu điểm vào khung hiển thị. Vì lý do này, hãy tránh sử dụng element.focus({preventScroll:true}), vì việc tập trung vào một phần tử không hiển thị là một trải nghiệm kém cho người dùng.

Nếu bạn muốn truy vấn tài liệu để tìm hiểu xem phần tử nào đang được lấy tiêu điểm, hãy sử dụng thuộc tính chỉ đọc Document.activeElement.

Các phần tử có tabindex từ 1 trở lên được đưa vào một chuỗi thẻ riêng biệt. Như bạn sẽ nhận thấy trong Codepen, việc nhấn phím Tab bắt đầu trong một chuỗi riêng biệt, theo thứ tự từ giá trị thấp nhất đến giá trị cao nhất, trước khi chuyển qua các giá trị trong chuỗi thông thường (không đặt tabindex hoặc tabindex="0") theo thứ tự nguồn:

tabindex có giá trị dương sẽ đặt phần tử vào một chuỗi tiêu điểm được ưu tiên, điều này có thể dẫn đến tình trạng lộn xộn về thứ tự tiêu điểm. Tránh sửa đổi thứ tự DOM bằng tabindex. Không chỉ tạo ra trải nghiệm không tốt cho người dùng, các thứ tự nhấn phím Tab bị thay đổi còn gây khó khăn cho nhà phát triển trong việc quản lý và duy trì.

Thuộc tính contenteditable

Thuộc tính contenteditable đã được thảo luận trước đó. Việc đặt contenteditable="true" trên bất kỳ phần tử nào sẽ giúp phần tử đó có thể chỉnh sửa, lấy tiêu điểm và nằm trong thứ tự nhấn phím Tab. Hành vi lấy tiêu điểm tương tự như hành vi đặt tabindex="0", nhưng không giống nhau. Các phần tử contenteditable lồng nhau có thể lấy tiêu điểm nhưng không thể dùng phím Tab. Để tạo một phần tử contenteditable lồng nhau có thể nhấn phím Tab, hãy thêm tabindex="0". Thao tác này sẽ thêm phần tử đó vào thứ tự điều hướng tiêu điểm tuần tự.

Cung cấp autofocus cho các phần tử tương tác

Mặc dù autofocus là một thuộc tính chung có thể được đặt trên mọi phần tử, nhưng thuộc tính này không làm cho một phần tử trơ trở nên có thể tương tác. Khi trang tải, phần tử có thể lấy tiêu điểm đầu tiên có thuộc tính autofocus sẽ nhận được tiêu điểm, miễn là phần tử đó xuất hiện và không được lồng trong <dialog>.

Việc tự động đặt tiêu điểm vào nội dung có thể gây nhầm lẫn. Việc đặt autofocus trên một thành phần kiểm soát biểu mẫu có nghĩa là thành phần kiểm soát biểu mẫu sẽ cuộn vào chế độ xem khi tải trang. Tất cả người dùng của bạn, bao gồm cả người dùng trình đọc màn hình và người dùng có khung hiển thị nhỏ, có thể không "thấy" hướng dẫn cho biểu mẫu, thậm chí có thể cuộn qua nhãn thường hiển thị của chế độ điều khiển biểu mẫu. Thuộc tính autofocus không làm thay đổi thứ tự điều hướng tiêu điểm tuần tự của tài liệu. Các phần tử trong chuỗi xuất hiện trước phần tử được tự động lấy tiêu điểm sẽ bị bỏ qua. Vì những lý do này, bạn không nên thêm thuộc tính autofocus.

Ngoại lệ đối với đề xuất "không sử dụng autofocus" là thêm thuộc tính autofocus trong các phần tử <dialog>. Khi một hộp thoại mở ra, trình duyệt sẽ tự động lấy tiêu điểm vào phần tử tương tác có thể lấy tiêu điểm đầu tiên trong <dialog>. Điều này có nghĩa là bạn không cần thêm autofocus vào một phần tử. Nếu bạn muốn đảm bảo một phần tử tương tác cụ thể trong hộp thoại nhận được tiêu điểm khi hộp thoại mở ra, hãy thêm thuộc tính autofocus vào phần tử đó.

<dialog open>
  <form method="dialog">
    <button type="submit" autofocus>close</button>
  </form>
</dialog>

Nhóm thuộc tính autofocus được đặt trên nút đóng <button> cho phép nút này nhận tiêu điểm khi hộp thoại mở ra. Là phần tử đầu tiên trong hộp thoại, phần tử này sẽ nhận được tiêu điểm trong mọi trường hợp. Theo mặc định, khi một hộp thoại được mở, phần tử có thể lấy tiêu điểm đầu tiên trong hộp thoại sẽ nhận được tiêu điểm, trừ phi một phần tử khác trong hộp thoại có thuộc tính autofocus được đặt.

Làm cho các phần tử tương tác trở nên trơ

Ngoài ra, còn có các thuộc tính HTML có thể xoá các phần tử tương tác khỏi chuỗi phím tab. Bao gồm một tabindex âm cho các phần tử có thể lấy tiêu điểm, thêm thuộc tính disabled vào các chế độ kiểm soát biểu mẫu hỗ trợ và thêm thuộc tính inert chung vào một vùng chứa đều khiến các phần tử không thể nhấn phím Tab. Bạn KHÔNG thể thay thế 3 thuộc tính này cho nhau.

Giá trị tabindex âm

Thuộc tính tabindex có giá trị âm giúp một phần tử có thể lấy tiêu điểm nhưng không thể dùng phím tab. Khi thêm tabindex="0" vào một phần tử có thể lấy tiêu điểm theo mặc định, bao gồm cả đường liên kết, nút, chế độ kiểm soát biểu mẫu và các phần tử contenteditable là không cần thiết; việc thêm tabindex có giá trị âm sẽ loại bỏ các phần tử thường có thể nhấn phím tab khỏi thứ tự điều hướng tiêu điểm tuần tự.

Giá trị tabindex âm sẽ ngăn người dùng bàn phím tập trung vào các phần tử tương tác, nhưng không vô hiệu hoá phần tử. Người dùng con trỏ vẫn có thể lấy tiêu điểm vào phần tử. Để tắt một phần tử, hãy dùng thuộc tính disabled.

Đã tắt

Thuộc tính boolean disabled khiến các thành phần điều khiển biểu mẫu mà thuộc tính này được áp dụng và các thành phần con của chúng (nếu có) không thể lấy tiêu điểm. Không thể lấy tiêu điểm các thành phần điều khiển biểu mẫu bị tắt, không nhận được sự kiện nhấp và không được gửi khi gửi biểu mẫu.

disabled không phải là thuộc tính chung. Thuộc tính này áp dụng cho <button>, <input>, <optgroup>, <option>, <select>, <textarea>, các phần tử tuỳ chỉnh liên kết với biểu mẫu và <fieldset>. Khi được đặt trên <optgroup> hoặc <fieldset>, tất cả các đối tượng kiểm soát biểu mẫu con đều bị tắt, ngoại trừ nội dung của <legend> đầu tiên của <fieldset>.

Bạn cũng có thể nhắm đến những phần tử hỗ trợ disabled bằng các lớp giả :disabled:enabled. Các phần tử bị vô hiệu hoá bằng thuộc tính disabled thường được tạo kiểu thành màu xám nhạt bằng biểu định kiểu tác nhân người dùng, ngay cả khi bạn đặt accent-color.

Là một thuộc tính boolean, sự hiện diện của thuộc tính này sẽ vô hiệu hoá phần tử được bật; bạn không thể đặt thuộc tính này thành false. Để bật lại một phần tử bị vô hiệu hoá, bạn phải xoá thuộc tính này, thường là bằng Element.removeAttribute('disabled').

Thuộc tính HTMLInputElement.disabled cho phép bạn kiểm tra xem một đầu vào có bị vô hiệu hoá hay không. Vì disabled không phải là một thuộc tính chung, nên thuộc tính này không được kế thừa từ HTMLElement, nhưng mọi giao diện phần tử hỗ trợ, chẳng hạn như HTMLSelectElement, HTMLTextareaElement, đều có cùng thuộc tính chỉ có thể đọc.

Thuộc tính disabled không áp dụng cho các phần tử inert thường được tạo thành tâm điểm bằng tabindex hoặc contenteditable, cũng như không áp dụng cho phần tử <form>. Để tắt các phần tử này, bạn có thể dùng thuộc tính inert chung.

Thuộc tính inert

Khi thuộc tính boolean inert chung được thêm vào một phần tử, phần tử đó và tất cả nội dung lồng ghép sẽ bị vô hiệu hoá, nghĩa là người dùng không thể nhấp hoặc nhấn phím Tab vào các phần tử đó. Các phần tử này cũng bị xoá khỏi cây hỗ trợ tiếp cận. Mặc dù bạn có thể áp dụng inert cho mọi phần tử, nhưng thẻ này thường được dùng cho các phần nội dung, chẳng hạn như nội dung bị che khuất hoặc bị ẩn.

Khi áp dụng disabled cho các thành phần điều khiển biểu mẫu, trình duyệt sẽ cung cấp kiểu mặc định và có thể được tạo kiểu bằng cách sử dụng lớp giả :disabled. Thuộc tính inert không cung cấp chỉ báo trực quan và không có giả lớp nào phù hợp (mặc dù bộ chọn thuộc tính [inert] phù hợp).

Việc sử dụng inert trên nội dung hiển thị mà không có kiểu cho biết trạng thái không hoạt động có thể dẫn đến trải nghiệm người dùng kém. Vì người dùng trình đọc màn hình không thể truy cập vào nội dung tĩnh, nên điều này có thể gây nhầm lẫn khi người dùng trình đọc màn hình có thị lực nhìn thấy nội dung trên màn hình mà các công cụ hỗ trợ tiếp cận không truy cập được. Làm cho trạng thái không hoạt động trở nên rất rõ ràng bằng CSS.

Đảm bảo rằng tiêu điểm không bao giờ di chuyển đến nội dung không hiển thị. Mọi nội dung được kết xuất ngoài màn hình và không tự động xuất hiện khi được lấy tiêu điểm đều phải được đặt ở trạng thái trơ. Nếu nội dung bị ẩn nhưng xuất hiện khi được lấy tiêu điểm, chẳng hạn như đường liên kết chuyển đến nội dung, thì bạn không cần phải đặt nội dung đó ở trạng thái tĩnh.

Kiểm tra mức độ hiểu biết của bạn

Kiểm tra kiến thức của bạn về tiêu điểm.

Nếu không thể lấy tiêu điểm cho một phần tử, thì phần tử đó sẽ được mô tả là gì?

Trống.
Hãy thử lại.
Trơ.
Chính xác!
Ẩn.
Hãy thử lại.

Điều gì sẽ đúng nếu phần tử có thuộc tính disabled?

Bạn sẽ không thể lấy nét được.
Chính xác!
Thông tin này sẽ không xuất hiện.
Hãy thử lại.
Nếu là một phần tử biểu mẫu, thì phần tử đó sẽ không được gửi.
Chính xác!