Hiện chú thích khi di chuột

Người dùng muốn xem thêm thông tin liên quan mà không cần thay đổi hoàn toàn bối cảnh. Việc hiển thị chú thích khi người dùng quan tâm đến thông tin khác có thể giúp cung cấp định nghĩa cho một thuật ngữ, làm rõ hành động mà nút chỉ có biểu tượng sẽ thực hiện hoặc cung cấp thêm hướng dẫn về trường biểu mẫu.

Tạo chú giải công cụ

Bạn có thể tạo một cửa sổ bật lên có hành vi bắt buộc bằng cách thêm thuộc tính popover="hint" vào <div> hoặc phần tử khác phù hợp về mặt ngữ nghĩa. Khi người dùng mở chú thích, thao tác này sẽ ẩn các chú thích popover="hint" khác nhưng không ẩn chú thích auto hoặc manual. Thành phần này cũng xử lý việc đóng chú thích lồng nhau.

Thuộc tính này cũng cung cấp hành vi đóng nhanh, vì vậy, khi người dùng nhấp hoặc lấy tiêu điểm bên ngoài cửa sổ bật lên, cửa sổ bật lên sẽ bị đóng.

Phần tử chú thích phải có thuộc tính id với giá trị duy nhất:

<!-- MANDATORY: The tooltip container `<div>` must have a `popover` attribute.
     the value of `"hint"` ensures it can be "light dismissed". -->
<div popover="hint" id="tooltip">Tooltip content</div>

Người dùng thể hiện sự quan tâm đến thông tin bổ sung bằng cách di chuột hoặc tập trung vào phần tử <a> hoặc <button>. Phần tử phải có thuộc tính interestfor khớp với thuộc tính id của chú thích.

<!-- The `interestfor` attribute can be applied to a `<button>` element: -->
<button interestfor="tooltip">Tooltip trigger</button>

<!-- The `interestfor` attribute can also be applied to an `<a>` element: -->
<a interestfor="tooltip" href="">Tooltip trigger</a>

Yếu tố kích hoạt phải có một chỉ báo trực quan để cho biết rằng có thêm thông tin khi tương tác với yếu tố kích hoạt.

Tính năng hỗ trợ tiếp cận được tích hợp vào interestfor

Khi bạn sử dụng interestfor, trình duyệt sẽ xử lý việc kết nối công nghệ hỗ trợ cho bạn:

  • Ngữ nghĩa ngầm ẩn: Mục tiêu có popover="hint" sẽ có vai trò tối thiểu ngầm ẩn là tooltip. KHÔNG tự đặt role="tooltip".
  • Liên kết ngầm: Trình duyệt liên kết ngầm phần tử nguồn với mục tiêu thông qua aria-describedby khi mục tiêu là văn bản thuần tuý hoặc thông qua aria-details khi mục tiêu chứa nội dung tương tác. KHÔNG thêm aria-describedby hoặc aria-details vào điều kiện kích hoạt.
  • Nội dung tương tác: Vì mối liên kết chuyển sang aria-details khi cần, nên mục tiêu ĐƯỢC PHÉP chứa nội dung tương tác (ví dụ: đường liên kết bên trong "thẻ mối quan tâm").

Các quy tắc ràng buộc về hỗ trợ tiếp cận (WCAG 1.4.13)

Ngay cả khi interestfor xử lý ngữ nghĩa ở trên, cách triển khai của bạn VẪN PHẢI đáp ứng WCAG 1.4.13 (Nội dung khi di chuột hoặc lấy tiêu điểm):

  • Có thể đóng: Người dùng phải có thể đóng chú thích mà không cần di chuyển con trỏ hoặc tiêu điểm bàn phím (ví dụ: bằng cách nhấn phím Escape). Thuộc tính popover gốc sẽ tự động quản lý mối liên kết này.
  • Có thể di chuột qua: Con trỏ phải có thể di chuyển qua chính nội dung chú thích mà không làm chú thích biến mất. Điều này cho phép người dùng sử dụng công cụ phóng to để đọc văn bản chú thích một cách an toàn.
  • Duy trì: Chú thích phải luôn hiển thị cho đến khi trình kích hoạt di chuột hoặc tiêu điểm bị xoá, người dùng đóng chú thích một cách rõ ràng hoặc nội dung của chú thích không còn hợp lệ.

Định vị chú giải công cụ

Chú thích được định vị bằng Định vị neo CSS. Khi chú thích được mở bằng interestfor, phần tử kích hoạt sẽ tự động trở thành neo ngầm ẩn cho cửa sổ bật lên.

Trong các trình duyệt hiện đại hỗ trợ định vị neo gốc, bạn không cần xác định anchor-name trên trình kích hoạt hoặc position-anchor trên chú thích. Bạn có thể định vị chú thích ngay bên cạnh điểm neo ngầm ẩn bằng cách sử dụng position-area và xử lý việc lật khi va chạm bằng position-try-fallbacks:

[popover] {
  /* Implicit anchor from interestfor: no anchor-name or position-anchor needed */
  position-area: top;
  position-try-fallbacks: flip-block;
  margin: unset;
}

Chiến lược dự phòng

Hỗ trợ dự phòng và trình duyệt cho trình gọi Interest

Trình gọi quan tâm phải được polyfill có điều kiện bằng cách sử dụng gói polyfill interestfor từ NPM. Ưu tiên gói polyfill hơn là sử dụng CDN.

BẮT BUỘC: Phát hiện tính năng bằng cách kiểm tra thuộc tính interestForElement trên HTMLButtonElement.prototype và chỉ tải polyfill khi thiếu tính năng hỗ trợ gốc.

<script type="module">
  if (!HTMLButtonElement.prototype.hasOwnProperty("interestForElement")) {
    // CDN link only used for example, prefer bundling.
    await import("https://unpkg.com/interestfor@latest");
  }
</script>

Lưu ý về Polyfill CSS

Khi sử dụng polyfill, CSS API sẽ thay đổi một chút để bù đắp cho việc thiếu lớp giả và thuộc tính gốc:

  • Lớp giả: Polyfill không thể xác định các lớp giả :interest-source và :interest-target thực, vì vậy, polyfill sẽ áp dụng các lớp .interest-source và .interest-target. BẮT BUỘC: Kết hợp các trạng thái này với :is() để hỗ trợ cả trạng thái gốc và trạng thái polyfill.
/* Styles to apply when the effect is being previewed */
:is(:interest-source, .interest-source) { /* ... */ }
:is(:interest-target, .interest-target) { /* ... */ }
  • Thuộc tính CSS: Đối với interest-delay, interest-delay-start và interest-delay-end, polyfill yêu cầu sử dụng các biến CSS vì không thể đọc trực tiếp các thuộc tính tuỳ chỉnh trong tất cả trình duyệt.
/* Adjust the start and end delay for interest invokers */
[interestfor] {
  --interest-delay-start: 0.2s;
  interest-delay-start: var(--interest-delay-start);
  --interest-delay-end: 0.1s;
  interest-delay-end: var(--interest-delay-end);
}

Phương án dự phòng và hỗ trợ trình duyệt cho Popover

Popover API chủ yếu là cải tiến tăng dần, nhưng các hành vi xác định của API này (quảng bá lớp trên cùng, đóng nhẹ và gọi popovertarget) không có hành vi tương đương chỉ dùng CSS. Các trình duyệt cũ cần có polyfill hoặc phương án dự phòng thủ công nếu bạn không muốn cung cấp polyfill.

Polyfill: Để hỗ trợ thuộc tính popover trong các trình duyệt cũ, hãy tải @oddbird/popover-polyfill theo điều kiện. BẮT BUỘC: Phát hiện tính năng bằng cách kiểm tra thuộc tính popover trên HTMLElement.prototype và chỉ tải polyfill khi thiếu tính năng hỗ trợ gốc — KHÔNG tải polyfill vô điều kiện.

Với trình đóng gói hoặc bản đồ nhập:

// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
  import("@oddbird/popover-polyfill");
}

Nếu không có trình đóng gói, hãy nhập từ CDN bên trong <script type="module">:

<script type="module">
  if (!("popover" in HTMLElement.prototype)) {
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  }
</script>

Lưu ý về kiểu: Polyfill không thể xác định lớp giả :popover-open thực, vì vậy, lớp này sẽ áp dụng lớp .\:popover-open. BẮT BUỘC: Kết hợp cả hai bằng :is() hoặc :where(), nếu không, các trình duyệt thiếu :popover-open sẽ loại bỏ toàn bộ quy tắc:

[popover]:is(:popover-open, .\:popover-open) {
  display: block;
}

Ngoài ra, đối với phương án dự phòng cũ không có polyfill, hãy sử dụng position: fixed và tính toán toạ độ theo cách thủ công thông qua getBoundingClientRect() hoặc dựa vào vị trí mặc định bằng inset: auto nếu điều đó phù hợp với trường hợp sử dụng.

popover-polyfill không polyfill hành vi gợi ý trong các trình duyệt hỗ trợ popover nhưng không hỗ trợ popover="hint". Đối với các trình duyệt đó, chú thích được mở thông qua tiêu điểm có thể vẫn mở khi chú thích thứ hai được mở thông qua thao tác di chuột.

Để hỗ trợ các trình duyệt không có tính năng định vị neo, bạn có thể sử dụng polyfill @oddbird/css-anchor-positioning. Ngoài ra, bạn có thể sử dụng @supports để chỉ định vị trí dự phòng.

Khi sử dụng polyfill @oddbird/css-anchor-positioning để hỗ trợ trình duyệt cũ, hãy lưu ý rằng polyfill không hỗ trợ neo ngầm định hoặc position-area trên cửa sổ bật lên. Đặt rõ ràng anchor-name trên điều kiện kích hoạt, đặt position-anchor trên cửa sổ bật lên và đặt vị trí bằng các hàm lồng ghép anchor() thay vì position-area:

<!-- MANDATORY: Conditionally install the anchor positioning polyfill -->
<script type="module">
  if (!("anchorName" in document.documentElement.style)) {
    await import("https://unpkg.com/@oddbird/css-anchor-positioning");
  }
</script>
button[interestfor="tooltip-attrs"] {
  /* MANDATORY: Each trigger and popover pair must have a unique anchor name, referenced by `anchor-name` on the trigger and `position-anchor` on the popover. */
  anchor-name: --tooltip-attrs;
}
#tooltip-attrs {
  position-anchor: --tooltip-attrs;
  /* If using the anchor positioning polyfill with a popover, DO use `anchor()` functions, and not `position-area. */
  top: anchor(bottom);
  left: anchor(right);
  margin: unset;
}