Xây dựng thành phần chú giải công cụ

Thông tin tổng quan cơ bản về cách tạo một phần tử tuỳ chỉnh cho chú thích thích ứng với màu sắc và dễ tiếp cận.

Trong bài đăng này, tôi muốn chia sẻ suy nghĩ của mình về cách tạo một phần tử tuỳ chỉnh <tool-tip> có thể thích ứng với màu sắc và dễ sử dụng. Hãy dùng thử bản minh hoạxem nguồn!

Chú giải công cụ xuất hiện trong nhiều ví dụ và bảng phối màu

Nếu bạn thích xem video, thì đây là phiên bản video của bài đăng này trên YouTube:

Tổng quan

Chú thích là một lớp phủ không theo phương thức, không chặn, không tương tác, chứa thông tin bổ sung cho giao diện người dùng. Theo mặc định, chú giải công cụ này sẽ bị ẩn và chỉ xuất hiện khi người dùng di chuột hoặc lấy tiêu điểm vào một phần tử được liên kết. Bạn không thể chọn hoặc tương tác trực tiếp với chú thích. Chú thích không thay thế cho nhãn hoặc thông tin có giá trị cao khác, người dùng phải có thể hoàn thành đầy đủ nhiệm vụ của mình mà không cần chú thích.

Nên: luôn gắn nhãn cho dữ liệu đầu vào.
Không: dựa vào chú thích thay vì nhãn

Toggletip so với Chú thích

Giống như nhiều thành phần, có nhiều nội dung mô tả về chú thích, ví dụ: trong MDN, WAI ARIA, Sarah HigleyInclusive Components. Tôi thích sự tách biệt giữa chú thích và chú thích bật/tắt. Chú thích phải chứa thông tin bổ sung không tương tác, trong khi chú thích bật/tắt có thể chứa tính năng tương tác và thông tin quan trọng. Lý do chính cho sự phân chia này là khả năng tiếp cận, cách người dùng dự kiến điều hướng đến cửa sổ bật lên và có quyền truy cập vào thông tin cũng như các nút trong cửa sổ đó. Chú thích bật/tắt nhanh chóng trở nên phức tạp.

Sau đây là video về một toggletip trên trang web Designcember; một lớp phủ có tính tương tác mà người dùng có thể ghim để mở và khám phá, sau đó đóng bằng thao tác đóng nhanh hoặc phím thoát:

Thử thách về giao diện người dùng này đi theo hướng của chú thích, tìm cách thực hiện hầu hết mọi thứ bằng CSS và đây là cách xây dựng chú thích đó.

Markup (note: đây là tên ứng dụng)

Tôi chọn sử dụng một phần tử tuỳ chỉnh <tool-tip>. Tác giả không cần biến các phần tử tuỳ chỉnh thành thành phần web nếu không muốn. Trình duyệt sẽ coi <foo-bar> giống như một <div>. Bạn có thể coi phần tử tuỳ chỉnh như một tên lớp có độ đặc hiệu thấp hơn. Không có JavaScript nào liên quan.

<tool-tip>A tooltip</tool-tip>

Đây là một thẻ div có chứa văn bản bên trong. Chúng ta có thể liên kết với cây hỗ trợ tiếp cận của các trình đọc màn hình có khả năng bằng cách thêm [role="tooltip"].

<tool-tip role="tooltip">A tooltip</tool-tip>

Giờ đây, đối với trình đọc màn hình, phần tử này được nhận dạng là chú giải công cụ. Trong ví dụ sau, bạn có thấy phần tử liên kết đầu tiên có một phần tử chú thích được nhận dạng trong cây của phần tử đó và phần tử thứ hai thì không? Người thứ hai không có vai trò này. Trong phần kiểu, chúng ta sẽ cải thiện chế độ xem dạng cây này.

Ảnh chụp màn hình Cây hỗ trợ tiếp cận của Công cụ của Chrome cho nhà phát triển, thể hiện HTML. Hiện một đường liên kết có văn bản &quot;top ; Has tooltip: Hey, a tooltip!&quot; (trên cùng; Có chú giải công cụ: Chào bạn, đây là chú giải công cụ!) có thể lấy tiêu điểm. Bên trong phần tử này là văn bản tĩnh &quot;top&quot; và một phần tử chú thích.

Tiếp theo, chúng ta cần chú thích không thể lấy tiêu điểm. Nếu trình đọc màn hình không hiểu vai trò của chú thích, thì trình đọc màn hình sẽ cho phép người dùng tập trung vào <tool-tip> để đọc nội dung và trải nghiệm người dùng không cần đến điều này. Trình đọc màn hình sẽ thêm nội dung vào phần tử mẹ và do đó, nội dung này không cần tiêu điểm để có thể truy cập. Ở đây, chúng ta có thể sử dụng inert để đảm bảo không người dùng nào vô tình tìm thấy nội dung chú thích này trong luồng thẻ của họ:

<tool-tip inert role="tooltip">A tooltip</tool-tip>

Một ảnh chụp màn hình khác về Cây hỗ trợ tiếp cận của Chrome DevTools, lần này thiếu phần tử chú thích.

Sau đó, tôi chọn sử dụng các thuộc tính làm giao diện để chỉ định vị trí của chú thích. Theo mặc định, tất cả <tool-tip> sẽ giả định vị trí "top", nhưng bạn có thể tuỳ chỉnh vị trí này trên một phần tử bằng cách thêm tip-position:

<tool-tip role="tooltip" tip-position="right ">A tooltip</tool-tip>

Ảnh chụp màn hình của một đường liên kết có chú thích ở bên phải cho biết &quot;Một chú thích&quot;.

Tôi có xu hướng sử dụng các thuộc tính thay vì các lớp cho những thứ như thế này để <tool-tip> không thể có nhiều vị trí được chỉ định cùng một lúc. Chỉ có thể có một hoặc không có.

Cuối cùng, hãy đặt các phần tử <tool-tip> bên trong phần tử mà bạn muốn cung cấp chú thích. Ở đây, tôi chia sẻ văn bản alt với người dùng có thị lực bằng cách đặt một hình ảnh và một <tool-tip> bên trong phần tử <picture>:

<picture>
  <img alt="The GUI Challenges skull logo" width="100" src="...">
  <tool-tip role="tooltip" tip-position="bottom">
    The <b>GUI Challenges</b> skull logo
  </tool-tip>
</picture>

Ảnh chụp màn hình của một hình ảnh có chú thích &quot;Biểu trưng đầu lâu GUI Challenges&quot;.

Ở đây, tôi đặt một <tool-tip> bên trong phần tử <abbr>:

<p>
  The <abbr>HTML <tool-tip role="tooltip" tip-position="top">Hyper Text Markup Language</tool-tip></abbr> abbr element.
</p>

Ảnh chụp màn hình của một đoạn văn có từ viết tắt HTML được gạch chân và một chú giải công cụ ở phía trên có nội dung &quot;Hyper Text Markup Language&quot; (Ngôn ngữ đánh dấu siêu văn bản).

Hỗ trợ tiếp cận

Vì tôi đã chọn tạo chú thích công cụ chứ không phải chú thích bật/tắt, nên phần này đơn giản hơn nhiều. Trước tiên, hãy để tôi trình bày trải nghiệm người dùng mà chúng tôi mong muốn:

  1. Trong không gian hạn chế hoặc giao diện lộn xộn, hãy ẩn các thông báo bổ sung.
  2. Khi người dùng di chuột, trỏ vào hoặc sử dụng thao tác chạm để tương tác với một phần tử, hãy hiển thị thông báo.
  3. Khi thao tác di chuột, lấy tiêu điểm hoặc chạm kết thúc, hãy ẩn thông báo.
  4. Cuối cùng, hãy đảm bảo rằng mọi chuyển động đều được giảm nếu người dùng đã chỉ định một lựa chọn ưu tiên cho chế độ giảm chuyển động.

Mục tiêu của chúng tôi là cung cấp thông báo bổ sung theo yêu cầu. Người dùng chuột hoặc bàn phím có thị lực có thể di chuột để hiển thị thông báo và đọc bằng mắt. Người dùng trình đọc màn hình không nhìn thấy có thể tập trung để hiển thị thông báo và nhận được thông báo đó bằng âm thanh thông qua công cụ của họ.

Ảnh chụp màn hình MacOS VoiceOver đọc một đường liên kết có chú thích

Trong phần trước, chúng ta đã đề cập đến cây hỗ trợ tiếp cận, vai trò chú thích và inert. Việc còn lại là kiểm thử và xác minh trải nghiệm người dùng một cách thích hợp để hiển thị thông báo chú thích cho người dùng. Khi kiểm thử, không rõ phần nào của thông báo có thể nghe được là chú giải công cụ. Bạn cũng có thể thấy điều này trong khi gỡ lỗi trong cây hỗ trợ tiếp cận, văn bản liên kết của "top" (trên cùng) được chạy cùng nhau, không do dự, với "Look, tooltips!" (Nhìn kìa, chú thích!). Trình đọc màn hình không ngắt hoặc xác định văn bản là nội dung chú thích.

Ảnh chụp màn hình Cây hỗ trợ tiếp cận của Công cụ của Chrome cho nhà phát triển, trong đó văn bản của đường liên kết là &quot;top Hey, a tooltip!&quot; (này, một chú thích!).

Thêm một phần tử giả chỉ dành cho trình đọc màn hình vào <tool-tip> và chúng ta có thể thêm văn bản lời nhắc của riêng mình cho người dùng khiếm thị.

&::before {
  content: "; Has tooltip: ";
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
}

Dưới đây, bạn có thể thấy cây hỗ trợ tiếp cận đã cập nhật, hiện có dấu chấm phẩy sau văn bản liên kết và một lời nhắc cho chú thích công cụ "Có chú thích công cụ: ".

Ảnh chụp màn hình mới của Cây hỗ trợ tiếp cận trong Chrome DevTools, trong đó văn bản liên kết đã được cải thiện cách diễn đạt: &quot;top ; Has tooltip: Hey, a tooltip!&quot; (đầu; Có chú thích: Này, một chú thích!).

Giờ đây, khi người dùng trình đọc màn hình đặt tiêu điểm vào đường liên kết, trình đọc màn hình sẽ nói "top" (đầu) và tạm dừng một chút, sau đó thông báo "has tooltip: look, tooltips" (có chú giải công cụ: xem, chú giải công cụ). Điều này giúp người dùng trình đọc màn hình có được một vài gợi ý hữu ích về trải nghiệm người dùng. Độ trễ này giúp tách biệt rõ ràng giữa văn bản liên kết và chú thích. Ngoài ra, khi "có chú thích" được thông báo, người dùng trình đọc màn hình có thể dễ dàng huỷ chú thích nếu đã nghe thấy chú thích đó trước đây. Điều này rất giống với việc di chuột và không di chuột nhanh, vì bạn đã thấy thông báo bổ sung. Điều này mang lại trải nghiệm người dùng tương đồng và dễ chịu.

Kiểu

Phần tử <tool-tip> sẽ là phần tử con của phần tử mà phần tử này đại diện cho thông báo bổ sung. Vì vậy, trước tiên, hãy bắt đầu với những điều cần thiết cho hiệu ứng lớp phủ. Loại bỏ khỏi quy trình chứng từ bằng cách position absolute:

tool-tip {
  position: absolute;
  z-index: 1;
}

Nếu thành phần mẹ không phải là một ngữ cảnh xếp chồng, thì chú thích sẽ tự định vị đến ngữ cảnh gần nhất, điều này không phải là điều chúng ta muốn. Có một bộ chọn mới trên khối có thể giúp ích, :has():

Browser Support

  • Chrome: 105.
  • Edge: 105.
  • Firefox: 121.
  • Safari: 15.4.

Source

:has(> tool-tip) {
  position: relative;
}

Đừng lo lắng quá nhiều về khả năng hỗ trợ trình duyệt. Trước tiên, hãy nhớ rằng những chú thích này chỉ mang tính bổ sung. Nếu không hoạt động thì cũng không sao. Thứ hai, trong phần JavaScript, chúng ta sẽ triển khai một tập lệnh để polyfill chức năng cần thiết cho các trình duyệt không hỗ trợ :has().

Tiếp theo, hãy làm cho chú thích không tương tác để chúng không lấy các sự kiện con trỏ từ phần tử mẹ:

tool-tip {
  
  pointer-events: none;
  user-select: none;
}

Sau đó, hãy ẩn chú thích bằng độ mờ để chúng ta có thể chuyển đổi chú thích bằng hiệu ứng làm mờ dần:

tool-tip {
  opacity: 0;
}

:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
}

:is():has() sẽ đảm nhận phần lớn công việc ở đây, giúp tool-tip chứa các phần tử mẹ nhận biết được khả năng tương tác của người dùng để bật/tắt chế độ hiển thị của chú thích con. Người dùng chuột có thể di chuột, người dùng bàn phím và trình đọc màn hình có thể lấy tiêu điểm, còn người dùng cảm ứng có thể nhấn.

Khi lớp phủ hiện và ẩn hoạt động đối với người dùng nhìn thấy, đã đến lúc thêm một số kiểu để tạo giao diện, định vị và thêm hình tam giác vào bong bóng. Các kiểu sau đây bắt đầu sử dụng các thuộc tính tuỳ chỉnh, dựa trên những gì chúng ta đã làm cho đến nay nhưng cũng thêm bóng, kiểu chữ và màu sắc để trông giống như một chú thích nổi:

Ảnh chụp màn hình của chú thích ở chế độ tối, nổi trên đường liên kết &quot;block-start&quot;.

tool-tip {
  --_p-inline: 1.5ch;
  --_p-block: .75ch;
  --_triangle-size: 7px;
  --_bg: hsl(0 0% 20%);
  --_shadow-alpha: 50%;

  --_bottom-tip: conic-gradient(from -30deg at bottom, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) bottom / 100% 50% no-repeat;
  --_top-tip: conic-gradient(from 150deg at top, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) top / 100% 50% no-repeat;
  --_right-tip: conic-gradient(from -120deg at right, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) right / 50% 100% no-repeat;
  --_left-tip: conic-gradient(from 60deg at left, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) left / 50% 100% no-repeat;

  pointer-events: none;
  user-select: none;

  opacity: 0;
  transform: translateX(var(--_x, 0)) translateY(var(--_y, 0));
  transition: opacity .2s ease, transform .2s ease;

  position: absolute;
  z-index: 1;
  inline-size: max-content;
  max-inline-size: 25ch;
  text-align: start;
  font-size: 1rem;
  font-weight: normal;
  line-height: normal;
  line-height: initial;
  padding: var(--_p-block) var(--_p-inline);
  margin: 0;
  border-radius: 5px;
  background: var(--_bg);
  color: CanvasText;
  will-change: filter;
  filter:
    drop-shadow(0 3px 3px hsl(0 0% 0% / var(--_shadow-alpha)))
    drop-shadow(0 12px 12px hsl(0 0% 0% / var(--_shadow-alpha)));
}

/* create a stacking context for elements with > tool-tips */
:has(> tool-tip) {
  position: relative;
}

/* when those parent elements have focus, hover, etc */
:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
  transition-delay: 200ms;
}

/* prepend some prose for screen readers only */
tool-tip::before {
  content: "; Has tooltip: ";
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
}

/* tooltip shape is a pseudo element so we can cast a shadow */
tool-tip::after {
  content: "";
  background: var(--_bg);
  position: absolute;
  z-index: -1;
  inset: 0;
  mask: var(--_tip);
}

/* top tooltip styles */
tool-tip:is(
  [tip-position="top"],
  [tip-position="block-start"],
  :not([tip-position]),
  [tip-position="bottom"],
  [tip-position="block-end"]
) {
  text-align: center;
}

Điều chỉnh giao diện

Chú thích chỉ có một vài màu để quản lý vì màu văn bản được kế thừa từ trang thông qua từ khoá hệ thống CanvasText. Ngoài ra, vì chúng ta đã tạo các thuộc tính tuỳ chỉnh để lưu trữ các giá trị, nên chúng ta chỉ có thể cập nhật các thuộc tính tuỳ chỉnh đó và để giao diện xử lý phần còn lại:

@media (prefers-color-scheme: light) {
  tool-tip {
    --_bg: white;
    --_shadow-alpha: 15%;
  }
}

Ảnh chụp màn hình đặt cạnh nhau của phiên bản sáng và tối của chú thích.

Đối với giao diện sáng, chúng tôi điều chỉnh nền thành màu trắng và giảm độ đậm của vùng tối bằng cách điều chỉnh độ mờ.

Phải sang trái

Để hỗ trợ chế độ đọc từ phải sang trái, một thuộc tính tuỳ chỉnh sẽ lưu trữ giá trị hướng của tài liệu thành giá trị lần lượt là -1 hoặc 1.

tool-tip {
  --isRTL: -1;
}

tool-tip:dir(rtl) {
  --isRTL: 1;
}

Bạn có thể dùng thuộc tính này để hỗ trợ việc định vị chú thích:

tool-tip[tip-position="top"]) {
  --_x: calc(50% * var(--isRTL));
}

Cũng như hỗ trợ xác định vị trí của tam giác:

tool-tip[tip-position="right"]::after {
  --_tip: var(--_left-tip);
}

tool-tip[tip-position="right"]:dir(rtl)::after {
  --_tip: var(--_right-tip);
}

Cuối cùng, bạn cũng có thể dùng để chuyển đổi logic trên translateX():

--_x: calc(var(--isRTL) * -3px * -1);

Vị trí của chú thích

Đặt chú thích một cách hợp lý bằng các thuộc tính inset-block hoặc inset-inline để xử lý cả vị trí chú thích thực tế và vị trí chú thích logic. Đoạn mã sau đây cho biết cách tạo kiểu cho từng vị trí trong số 4 vị trí cho cả hướng từ trái sang phải và từ phải sang trái.

Căn chỉnh theo lề trên và đầu khối

Ảnh chụp màn hình cho thấy sự khác biệt về vị trí giữa vị trí trên cùng từ trái sang phải và vị trí trên cùng từ phải sang trái.

tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position])) {
  inset-inline-start: 50%;
  inset-block-end: calc(100% + var(--_p-block) + var(--_triangle-size));
  --_x: calc(50% * var(--isRTL));
}

tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position]))::after {
  --_tip: var(--_bottom-tip);
  inset-block-end: calc(var(--_triangle-size) * -1);
  border-block-end: var(--_triangle-size) solid transparent;
}

Căn phải và căn ở cuối dòng

Ảnh chụp màn hình cho thấy sự khác biệt về vị trí đặt giữa vị trí bên phải từ trái sang phải và vị trí cuối dòng từ phải sang trái.

tool-tip:is([tip-position="right"], [tip-position="inline-end"]) {
  inset-inline-start: calc(100% + var(--_p-inline) + var(--_triangle-size));
  inset-block-end: 50%;
  --_y: 50%;
}

tool-tip:is([tip-position="right"], [tip-position="inline-end"])::after {
  --_tip: var(--_left-tip);
  inset-inline-start: calc(var(--_triangle-size) * -1);
  border-inline-start: var(--_triangle-size) solid transparent;
}

tool-tip:is([tip-position="right"], [tip-position="inline-end"]):dir(rtl)::after {
  --_tip: var(--_right-tip);
}

Căn chỉnh theo lề dưới và cuối khối

Ảnh chụp màn hình cho thấy sự khác biệt về vị trí giữa vị trí dưới cùng từ trái sang phải và vị trí cuối khối từ phải sang trái.

tool-tip:is([tip-position="bottom"], [tip-position="block-end"]) {
  inset-inline-start: 50%;
  inset-block-start: calc(100% + var(--_p-block) + var(--_triangle-size));
  --_x: calc(50% * var(--isRTL));
}

tool-tip:is([tip-position="bottom"], [tip-position="block-end"])::after {
  --_tip: var(--_top-tip);
  inset-block-start: calc(var(--_triangle-size) * -1);
  border-block-start: var(--_triangle-size) solid transparent;
}

Căn trái và căn chỉnh theo hướng bắt đầu của dòng

Ảnh chụp màn hình cho thấy sự khác biệt về vị trí giữa vị trí bên trái từ trái sang phải và vị trí bắt đầu nội tuyến từ phải sang trái.

tool-tip:is([tip-position="left"], [tip-position="inline-start"]) {
  inset-inline-end: calc(100% + var(--_p-inline) + var(--_triangle-size));
  inset-block-end: 50%;
  --_y: 50%;
}

tool-tip:is([tip-position="left"], [tip-position="inline-start"])::after {
  --_tip: var(--_right-tip);
  inset-inline-end: calc(var(--_triangle-size) * -1);
  border-inline-end: var(--_triangle-size) solid transparent;
}

tool-tip:is([tip-position="left"], [tip-position="inline-start"]):dir(rtl)::after {
  --_tip: var(--_left-tip);
}

Hoạt ảnh

Cho đến nay, chúng ta chỉ bật/tắt chế độ hiển thị của chú thích. Trong phần này, trước tiên, chúng ta sẽ tạo hiệu ứng cho độ mờ của tất cả người dùng, vì đây thường là hiệu ứng chuyển động giảm an toàn. Sau đó, chúng ta sẽ tạo ảnh động cho vị trí biến đổi để chú thích xuất hiện và trượt ra khỏi phần tử mẹ.

Quá trình chuyển đổi mặc định an toàn và có ý nghĩa

Tạo kiểu cho phần tử chú thích để chuyển đổi độ mờ và biến đổi, như sau:

tool-tip {
  opacity: 0;
  transform: translateX(var(--_x, 0)) translateY(var(--_y, 0));
  transition: opacity .2s ease, transform .2s ease;
}

:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
  transition-delay: 200ms;
}

Thêm chuyển động vào hiệu ứng chuyển cảnh

Đối với mỗi bên mà chú thích có thể xuất hiện, nếu người dùng chấp nhận chuyển động, hãy đặt thuộc tính translateX một chút bằng cách cho thuộc tính này một khoảng cách nhỏ để di chuyển từ:

@media (prefers-reduced-motion: no-preference) {
  :has(> tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position]))):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_y: 3px;
  }

  :has(> tool-tip:is([tip-position="right"], [tip-position="inline-end"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_x: -3px;
  }

  :has(> tool-tip:is([tip-position="bottom"], [tip-position="block-end"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_y: -3px;
  }

  :has(> tool-tip:is([tip-position="left"], [tip-position="inline-start"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_x: 3px;
  }
}

Lưu ý rằng thao tác này đang đặt trạng thái "out" (ra ngoài), vì trạng thái "in" (vào trong) là ở translateX(0).

JavaScript

Theo tôi, JavaScript là không bắt buộc. Điều này là do không có chú thích nào trong số này là nội dung bắt buộc phải đọc để hoàn thành một tác vụ trong giao diện người dùng. Vì vậy, nếu chú thích hoàn toàn không hoạt động, thì cũng không có gì đáng lo ngại. Điều này cũng có nghĩa là chúng ta có thể coi chú thích là được cải tiến dần. Cuối cùng, tất cả trình duyệt sẽ hỗ trợ :has() và tập lệnh này có thể hoàn toàn biến mất.

Tập lệnh polyfill thực hiện 2 việc và chỉ thực hiện nếu trình duyệt không hỗ trợ :has(). Trước tiên, hãy kiểm tra xem có hỗ trợ :has() hay không:

if (!CSS.supports('selector(:has(*))')) {
  // do work
}

Tiếp theo, hãy tìm các phần tử mẹ của <tool-tip> và đặt cho chúng một tên lớp để làm việc:

if (!CSS.supports('selector(:has(*))')) {
  document.querySelectorAll('tool-tip').forEach(tooltip =>
    tooltip.parentNode.classList.add('has_tool-tip'))
}

Tiếp theo, hãy chèn một nhóm kiểu sử dụng tên lớp đó, mô phỏng bộ chọn :has() để có chính xác cùng một hành vi:

if (!CSS.supports('selector(:has(*))')) {
  document.querySelectorAll('tool-tip').forEach(tooltip =>
    tooltip.parentNode.classList.add('has_tool-tip'))

  let styles = document.createElement('style')
  styles.textContent = `
    .has_tool-tip {
      position: relative;
    }
    .has_tool-tip:is(:hover, :focus-visible, :active) > tool-tip {
      opacity: 1;
      transition-delay: 200ms;
    }
  `
  document.head.appendChild(styles)
}

Vậy là xong, giờ đây, tất cả trình duyệt sẽ vui vẻ hiển thị chú thích nếu không hỗ trợ :has().

Kết luận

Giờ thì bạn đã biết cách tôi làm, còn bạn thì sao‽ 🙂 Tôi rất mong chờ API popup để tạo toggletip dễ dàng hơn, lớp trên cùng để không phải lo lắng về chỉ mục z và API anchor để định vị mọi thứ trong cửa sổ một cách hiệu quả hơn. Cho đến lúc đó, tôi sẽ tạo chú thích.

Hãy đa dạng hoá các phương pháp và tìm hiểu tất cả các cách để xây dựng trên web.

Hãy tạo một bản minh hoạ, gửi đường liên kết cho tôi qua Twitter và tôi sẽ thêm bản minh hoạ đó vào phần bản phối lại của cộng đồng bên dưới!

Bản phối lại của cộng đồng

Chưa có nội dung nào ở đây.

Tài nguyên