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à có thể dùng phím Tab để di chuyển. 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 di chuyển 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 xấu đến trải nghiệm người dùng.

Không được thay đổi thứ tự lập bảng 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 thị giác 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ụ sau, giá trị của thuộc tính tabindex đã khiến thứ tự thẻ bị xáo trộ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 (thứ tự) của CSS đã được áp dụng cho từ thứ sáu ("This"), giúp di chuyển từ đó một cách trực quan. Trình 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. Điều này khiến người dùng bàn phím cảm thấy không liên quan.

Một số tính năng CSS, bao gồm flexbox, lưới, định vị, biến đổinhiều cột, có thể làm thay đổi thứ tự hiển thị của nội dung. Kiểm thử nội dung bằng cách nhấn phím tab để di chuyển qua nội dung bằng bàn phím: nhấn tổ hợp phím shift + tab để di chuyển ngược lại qua nội dung. Sử dụng CSS để cho biết phần tử nào đang được lấy tiêu điểm. Không sắp xếp lại các phần tử có thể lấy tiêu điểm bằng CSS.

Điều quan trọng là bạn phải duy trì thứ tự nhấn phím Tab hợp lý trên mọi kích thước khung nhìn.

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. Các phần tử có thể làm tiêu điểm cũng có thể được 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 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ể dùng 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 sẽ giúp 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ử này vào thứ tự nhấn phím 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>

Ngoài ra, thanh điều hướng cục bộ có một phần tử tuỳ chỉnh có 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ể chuyển tiêu điểm bằ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 thành phần tương tác, phần tử đó sẽ không còn có thể nhấn 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 chế độ xem. 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 nhìn thấy được sẽ mang lại 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 trình tự thẻ riêng biệt. Như trong Codepen sau đây, 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. Việc thay đổi thứ tự nhấn phím tab có thể tạo ra trải nghiệm không tốt cho người dùng và khó 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ư việc đặ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ự.

Thêm autofocus vào các phần tử tương tác

Mặc dù boolean 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 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ử đó được hiển thị và không được lồng trong <dialog>.

Việc tự động đặt tiêu điểm vào nội dung có thể khiến người dùng nhầm lẫn. Khi bạn đặt autofocus trên một thành phần điều khiển biểu mẫu, thành phần điều khiển biểu mẫu đó sẽ cuộn vào chế độ xem khi tải trang. 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ể bỏ lỡ hướng dẫn của biểu mẫu hoặc thậm chí là nhãn của chế độ điều khiển biểu mẫu. Ngoài ra, 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 nên tránh sử dụng 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 trên thành phần tương tác có thể làm tiêu điểm đầu tiên trong <dialog>, tức 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 thành phần 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>

Tập hợp thuộc tính autofocus được đặt trên <button> đóng cho phép nó nhận tiêu điểm khi hộp thoại được mở. 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ử đầu tiên có thể lấy tiêu điểm 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 trình tự nhấn phím tab. Việc thêm một tabindex âm vào 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 áp dụng cho mọi thành phần vào một vùng chứa sẽ khiến các phần tử không thể nhấn phím Tab. Ba thuộc tính này hoàn toàn riêng biệt và không thể thay thế 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ế độ điều khiển 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ể tập trung 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ể sử dụng thuộc tính inert chung.

Thuộc tính inert

Khi thuộc tính boolean chung inert đượ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 nội dung bị ẩn.

Khi áp dụng disabled cho các chế độ kiểm soát 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 khớp (mặc dù bộ chọn thuộc tính [inert] khớ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 nhưng các công cụ hỗ trợ tiếp cận lại 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 nhìn thấy được. 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 không hoạt động. 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 không hoạt động.

Kiểm tra kiến thức 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.
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!