Tiêu điểm kiểu

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

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

Dùng :focus để luôn hiện chỉ báo lấy nét

Lớp giả :focus được áp dụng mỗi khi một phần tử được 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 tiêu điểm là gì. Ví dụ: <div> dưới đây có tabindex khiến nó có thể làm tâm điểm. Lớp 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 dùng chuột để nhấp vào hay sử dụng bàn phím để nhấn vào, <div> sẽ luôn trông giống nhau.

Rất tiếc, cách các trình duyệt áp dụng tiêu điểm có thể không nhất quán. 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 chuột vào <button> trong Chrome trên macOS, bạn sẽ thấy kiểu tiêu điểm tuỳ chỉnh của Chrome. 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. Nguyên nhân là do trong Safari, phần tử đó không nhận được tiêu điểm khi bạn nhấp vào đó.

Vì hành vi của tiêu điểm không nhất quán, nên có thể cần phải thử nghiệm một chút trên các thiết bị khác nhau để đảm bảo kiểu tiêu điểm của bạn được người dùng chấp nhận được.

Dùng :focus-visible để hiển thị có chọn lọc một chỉ báo lấy nét

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 lấy tiêu điểm sẽ có lợi cho người dùng. Cụ thể, nếu hoạt động tương tác gần đây nhất của người dùng là thông 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ẽ hiển thị chỉ báo lấy nét có chọn lọc. Nếu bạn dùng chuột để nhấp vào biểu tượng đó, các kết quả sẽ khác với khi bạn lần đầu sử dụng bàn phím để nhấn vào biểu tượng đó.

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

Dùng :focus-within để tạo kiểu cho phần tử mẹ của phần tử có 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 thanh này để đánh dấu một vùng trên trang để thu hút sự chú ý của người dùng đến vùng đó. Ví dụ: biểu mẫu bên dưới nhận được tâm điểm cả khi chính biểu mẫu đó được chọn và cả khi bất kỳ nút chọn nào trong biểu mẫu được chọn.

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

Thời điểm hiển thị chỉ báo lấy nét

Nguyên tắc chung là hãy tự hỏi "Nếu bạn nhấp vào điều khiển này trong khi sử dụng thiết bị di động, bạn có mong đợi 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 phải luôn hiển thị chỉ báo lấy nét, bất kể thiết bị đầu vào 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ẽ phải gửi dữ liệu đầu vào cho phần tử thông qua bàn phím bất kể phần tử đầu vào đó nhận tiêu điểm như thế nào lúc đầu. Vì vậy, sẽ rất hữu ích khi luôn hiển thị chỉ báo lấy nét.

Nếu câu trả lời là "không", thì chế độ điều khiển này có thể chọn hiển thị một chỉ báo lấy 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 bằng chuột hoặc màn hình cảm ứng, thì thao tác đã hoàn tất và có thể không cần chỉ báo lấy nét. Tuy nhiên, nếu đ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 chế độ điều khiển bằng cách sử dụng phím ENTER hoặc SPACE hay không.

Tránh outline: none

Thật lòng mà nói, cách thức các trình duyệt quyết định thời điểm vẽ chỉ báo lấy nét 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ử tabindex sẽ khiến hành vi vòng lấy nét mặc định của trình duyệt xuất hiện.

Một cách phản đối rất phổ biến là xoá chỉ báo lấy nét bằng CSS chẳng hạn như:

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

Một cách hiệu quả 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 dưới đây minh hoạ cách hoạt động của polyfill, ứng dụng mẫu bên dưới khối này đưa ra ví dụ về cách sử dụng polyfill để thay đổi chỉ báo lấy nét 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 {
  …
}