Tiêu điểm kiểu

Chỉ báo tiêu điểm (thường được biểu thị bằng "vòng tiêu điểm") xác định phần tử hiện đang được lấy tiêu điểm trên trang. Đối với những người dùng không thể sử dụng chuột, chỉ báo này rất quan trọng vì nó đóng vai trò thay thế con trỏ chuột.

Nếu chỉ báo tiêu điểm mặc định của trình duyệt xung đột với thiết kế của bạn, bạn có thể sử dụng CSS để định kiểu lại chỉ báo đó. Chỉ cần nhớ lưu ý đến người dùng bàn phím!

Lớp giả :focus được áp dụng bất cứ khi nào một phần tử được lấy làm tâm điểm, bất kể thiết bị đầu vào (chuột, bàn phím, bút cảm ứng, v.v.) hoặc phương thức dùng để lấy làm tâm điểm. Ví dụ: <div> bên dưới có tabindex giúp bạn có thể lấy tiêu điểm. Đoạn mã này cũng có một kiểu tuỳ chỉnh cho trạng thái :focus:

div[tabindex="0"]:focus {
  outline: 4px dashed orange;
}

Bất kể bạn sử dụng chuột để nhấp vào nút này hay bàn phím để chuyển đến nút này, <div> sẽ luôn trông giống nhau.

Rất tiếc, trình duyệt có thể không nhất quán với cách áp dụng tiêu điểm. Việc một phần tử có nhận được tiêu điểm hay không có thể tuỳ thuộc vào trình duyệt và hệ điều hành.

Ví dụ: <button> bên dưới cũng có một kiểu tuỳ chỉnh cho trạng thái :focus.

button:focus {
  outline: 4px dashed orange;
}

Nếu nhấp vào <button> bằng chuột trong Chrome trên macOS, bạn sẽ thấy kiểu tiêu điểm tuỳ chỉnh. Tuy nhiên, bạn sẽ không thấy kiểu tiêu điểm tuỳ chỉnh nếu nhấp vào <button> trong Safari trên macOS. Điều này là do trong Safari, phần tử không nhận được tiêu điểm khi bạn nhấp vào phần tử đó.

Do hành vi lấy nét không nhất quán, nên có thể bạn phải kiểm thử một chút trên các thiết bị khác nhau để đảm bảo rằng người dùng có thể chấp nhận kiểu lấy nét của bạn.

Sử dụng :focus-visible để hiển thị chọn lọc chỉ báo tiêu điểm

Lớp giả :focus-visible mới được áp dụng bất cứ khi nào một phần tử nhận được tiêu điểm và trình duyệt xác định thông qua phương pháp phỏng đoán rằng việc hiển thị chỉ báo tiêu điểm sẽ có lợi cho người dùng. Cụ thể, nếu lượt tương tác gần đây nhất của người dùng là qua bàn phím và thao tác nhấn phím không bao gồm phím meta, ALT / OPTION hoặc CONTROL, thì :focus-visible sẽ khớp.

Nút trong ví dụ bên dưới sẽ có chọn lọc hiển thị chỉ báo tiêu điểm. Nếu bạn nhấp vào chuột để nhấp vào, kết quả sẽ khác với khi bạn dùng bàn phím để nhấp vào đó lần đầu.

button:focus-visible {
  outline: 4px dashed orange;
}

Dùng :focus-within để tạo kiểu cho phần tử mẹ của một phần tử được lấy tiêu điểm

Lớp giả :focus-within được áp dụng cho một phần tử khi chính phần tử đó nhận được tiêu điểm hoặc khi một phần tử khác bên trong phần tử đó nhận được tiêu điểm.

Bạn có thể dùng hiệu ứng này để làm nổi bật một khu vực trên trang nhằm thu hút sự chú ý của người dùng đến khu vực đó. Ví dụ: biểu mẫu bên dưới nhận được tiêu điểm cả khi chính biểu mẫu được chọn và khi bất kỳ nút chọn nào của biểu mẫu được chọn.

form:focus-within {
  background: #ffecb3;
}

Thời điểm hiển thị chỉ báo tiêu điểm

Bạn nên tự hỏi: "Nếu nhấp vào nút điều khiển này khi sử dụng thiết bị di động, bạn có muốn nút điều khiển đó hiển thị bàn phím không?"

Nếu câu trả lời là "có", thì chế độ điều khiển có thể luôn hiển thị chỉ báo lấy tiêu điểm, bất kể thiết bị đầu vào được sử dụng để lấy nét là gì. Một ví dụ điển hình là phần tử <input type="text">. Người dùng sẽ cần gửi dữ liệu đầu vào đến thành phần thông qua bàn phím, bất kể thành phần đầu vào ban đầu nhận được tiêu điểm như thế nào. Vì vậy, bạn nên luôn hiển thị chỉ báo tiêu điểm.

Nếu câu trả lời là "không", thì thành phần điều khiển có thể chọn hiển thị chỉ báo tiêu điểm một cách có chọn lọc. Một ví dụ điển hình là phần tử <button>. Nếu người dùng nhấp vào nút đó bằng chuột hoặc màn hình cảm ứng, thao tác sẽ hoàn tất và có thể không cần chỉ báo tiêu điểm. Tuy nhiên, nếu người dùng đang di chuyển bằng bàn phím, thì bạn nên hiển thị chỉ báo tiêu điểm để người dùng có thể quyết định xem họ có muốn nhấp vào nút điều khiển bằng phím ENTER hay SPACE hay không.

Tránh outline: none

Thú thực là việc các trình duyệt quyết định thời điểm vẽ chỉ báo tiêu điểm rất khó hiểu. Việc thay đổi giao diện của phần tử <button> bằng CSS hoặc cung cấp cho phần tử một tabindex sẽ khiến hành vi vòng tiêu điểm mặc định của trình duyệt bắt đầu hoạt động.

Một mẫu chống rất phổ biến là xoá chỉ báo tiêu điểm bằng CSS, chẳng hạn như:

/* Don't do this!!! */
:focus {
  outline: none;
}

Một cách tốt hơn để giải quyết vấn đề này là sử dụng kết hợp :focus và polyfill :focus-visible. Khối mã đầu tiên bên dưới minh hoạ cách hoạt động của polyfill và ứng dụng mẫu bên dưới cung cấp ví dụ về cách sử dụng polyfill để thay đổi chỉ báo tiêu điểm trên một nút.

/*
  This will hide the focus indicator if the element receives focus via the
  mouse, but it will still show up on keyboard focus.
*/
.js-focus-visible :focus:not(.focus-visible) {
  outline: none;
}

/*
  Optionally: Define a strong focus indicator for keyboard focus.
  If you choose to skip this step, then the browser's default focus
  indicator will be displayed instead.
*/
.js-focus-visible .focus-visible {
  
}