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 của chú giải công cụ có thể tiếp cận và thích ứng với màu sắc.

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ễ tiếp cận. Dùng thử bản minh hoạxem mã nguồn!

Chú giải công cụ hiển thị hoạt động trên nhiều ví dụ và bảng phối màu

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

Tổng quan

Chú giải công cụ là một lớp phủ không giao diện, 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. Thành phần này bị ẩn theo mặc định và sẽ xuất hiện khi một phần tử được liên kết được di chuột qua hoặc được lấy làm tâm điểm. Bạn không thể chọn hoặc tương tác trực tiếp với chú giải công cụ. Chú giải công cụ 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 toàn bộ nhiệm vụ của mình mà không cần chú giải công cụ.

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

Toggletip so với Tooltip

Giống như nhiều thành phần, có nhiều nội dung mô tả về chú giải công cụ, chẳng hạn như trong MDN, WAI ARIA, Sarah HigleyThành phần bao gồm. Tôi thích cách phân tách giữa chú giải công cụ và chú giải bật/tắt. Chú giải công cụ phải chứa thông tin bổ sung không tương tác, trong khi chú giải bật/tắt có thể chứa thông tin tương tác và quan trọng. Lý do chính dẫn đến sự phân chia này là khả năng hỗ trợ tiếp cận, cách người dùng dự kiến sẽ đ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 đó. Toggletips nhanh chóng trở nên phức tạp.

Dưới đây là video về một nút bật/tắt 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 nhẹ hoặc phím thoát:

Thách thức về giao diện người dùng này đã đi theo hướng của chú giải công cụ, tìm cách thực hiện hầu hết mọi việc bằng CSS. Dưới đây là cách tạo chú giải công cụ.

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

Tôi chọn sử dụng phần tử tuỳ chỉnh <tool-tip>. Tác giả không cần phải tạo các thành phần tùy 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ư <div>. Bạn có thể coi một phần tử tuỳ chỉnh như một tên lớp có mức độ cụ thể thấp hơn. Không có JavaScript nào liên quan.

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

Đây giống như một div có một số 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ụ. Hãy xem ví dụ sau đây để biết cách phần tử đường liên kết đầu tiên có phần tử chú giải công cụ được nhận dạng trong cây của phần tử đó và phần tử thứ hai không có phần tử chú giải công cụ. Người dùng thứ hai không có vai trò này. Trong phần kiểu, chúng ta sẽ cải thiện chế độ xem cây này.

Ảnh chụp màn hình Cây hỗ trợ tiếp cận trong Công cụ của Chrome cho nhà phát triển đại diện cho HTML. Hiển thị 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ụ: Này, một chú giải công cụ!). Bạn có thể đặt tiêu điểm vào đường liên kết này. Bên trong là văn bản tĩnh &quot;top&quot; (trên cùng) và một phần tử chú giải công cụ.

Tiếp theo, chúng ta cần chú giải công cụ 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ú giải công cụ, thì trình đọc màn hình sẽ cho phép người dùng đặt tiêu điểm vào <tool-tip> để đọc nội dung và trải nghiệm người dùng không cầ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 đó, phần tử 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 có người dùng nào vô tình tìm thấy nội dung chú giải công cụ này trong luồng thẻ:

<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 trong Chrome DevTools, lần này bị thiếu phần tử chú giải công cụ.

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ú giải công cụ. Theo mặc định, tất cả <tool-tip> sẽ giả định vị trí "trên cùng", nhưng bạn có thể tuỳ chỉnh vị trí 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ú giải công cụ ở bên phải với nội dung &quot;Chú giải công cụ&quot;.

Tôi thường sử dụng các thuộc tính thay vì lớp cho những trường hợp 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ú giải công cụ. Ở đâ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à <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ú giải công cụ có nội dung &quot;Biểu trưng đầu lâu của GUI Challenges&quot;.

Ở đây, tôi đặ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 một đoạn văn bản có từ viết tắt HTML được gạch chân và 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ú giải công cụ chứ không phải chú giải bật/tắt, nên phần này sẽ đơ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 ta mong muốn:

  1. Trong không gian bị hạn chế hoặc giao diện lộn xộn, hãy ẩn thông báo bổ sung.
  2. Khi người dùng di chuột, đặt tiêu điểm 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 lại thông báo.
  4. Cuối cùng, hãy đảm bảo mọi chuyển động đều được giảm nếu người dùng đã chỉ định một tuỳ chọn ưu tiên 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 bình thường có thể di chuột để hiển thị thông báo, đọc thông báo bằng mắt. Người dùng trình đọc màn hình khiếm thị có thể tập trung để hiển thị thông báo, nhận thông báo bằng âm thanh thông qua công cụ của họ.

Ảnh chụp màn hình VoiceOver trên MacOS đọc một đường liên kết có chú giải công cụ

Trong phần trước, chúng ta đã đề cập đến cây hỗ trợ tiếp cận, vai trò của chú giải công cụ và tính chất không hoạt động. Việc còn lại là kiểm thử và xác minh trải nghiệm người dùng hiển thị thông báo chú giải công cụ cho người dùng một cách phù hợp. Sau khi kiểm thử, không rõ phần nào của thông báo bằng âm thanh 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 đường 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ú giải công cụ!). 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ú giải công cụ.

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

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;
}

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

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

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ẽ đọc "top" (trên cùng) 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 cung cấp cho người dùng trình đọc màn hình một số gợi ý về trải nghiệm người dùng. Độ trễ này tạo ra sự phân tách rõ ràng giữa văn bản liên kết và chú giải công cụ. Ngoài ra, khi thông báo "có chú giải công cụ" được đưa ra, người dùng trình đọc màn hình có thể dễ dàng huỷ thông báo đó nếu họ đã nghe thấy thông báo đó trước đây. Thao tác này rất giống với việc di chuột và di chuột ra nhanh chóng, vì bạn đã thấy thông báo bổ sung. Đây là một trải nghiệm người dùng đồng nhất.

Kiểu

Phần tử <tool-tip> sẽ là phần tử con của phần tử mà nó đạ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 yếu tố cần thiết cho hiệu ứng lớp phủ. Loại bỏ khỏi quy trình tài liệu bằng position absolute:

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

Nếu thành phần mẹ không phải là ngữ cảnh xếp chồng, thì chú giải công cụ sẽ tự định vị đến thành phần mẹ gần nhất, đâ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 bạn, :has():

Hỗ trợ trình duyệt

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

Nguồn

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

Đừng quá lo lắng về việc hỗ trợ trình duyệt. Trước tiên, hãy nhớ rằng các chú giải công cụ này là 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ú giải công cụ không tương tác để không đánh cắp các sự kiện con trỏ từ phần tử mẹ:

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

Sau đó, ẩn chú giải công cụ bằng độ mờ để chúng ta có thể chuyển đổi chú giải công cụ bằng hiệu ứng chuyển tiếp:

tool-tip {
  opacity: 0;
}

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

:is():has() thực hiệ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ú giải công cụ 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 và người dùng cảm ứng có thể nhấn.

Khi lớp phủ hiển thị và ẩn hoạt động cho người dùng có thị lực, đã đế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 trò chuyện. 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 đã có nhưng cũng thêm bóng, kiểu chữ và màu sắc để trông giống như một chú giải công cụ nổi:

Ảnh chụp màn hình chú giải công cụ ở 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ú giải công cụ 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 cạnh nhau của các phiên bản chú giải công cụ sáng và tối.

Đối với giao diện sáng, chúng ta điều chỉnh nền thành màu trắng và làm cho bóng mờ hơn 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ị của hướng tài liệu thành giá trị -1 hoặc 1 tương ứng.

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

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

Bạn có thể sử dụng thông tin này để hỗ trợ định vị chú giải công cụ:

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

Cũng như hỗ trợ trong việc 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ể sử dụng hàm này cho các phép biến đổi logic trên translateX():

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

Vị trí chú giải công cụ

Đặt chú giải công cụ 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ú giải công cụ thực tế và logic. 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 trên cùng và bắt đầu khối

Ảnh chụp màn hình cho thấy sự khác biệt về vị trí đặt 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 chỉnh cuối cùng cùng dòng

Ảnh chụp màn hình cho thấy sự khác biệt về vị trí đặt quảng cáo giữa vị trí bên phải từ trái sang phải và vị trí cuối cùng cùng 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 dưới cùng và cuối khối

Ảnh chụp màn hình cho thấy sự khác biệt về vị trí đặt 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 đầu dòng

Ảnh chụp màn hình cho thấy sự khác biệt về vị trí đặt quảng cáo giữa vị trí bên trái từ trái sang phải và vị trí bắt đầu cùng dòng 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ú giải công cụ. Trong phần này, trước tiên chúng ta sẽ tạo ảnh động độ mờ cho tất cả người dùng, vì đây là hiệu ứng chuyển đổi chuyển động giảm thường an toàn. Sau đó, chúng ta sẽ tạo ảnh động cho vị trí biến đổi để chú giải công cụ có vẻ như trượt ra khỏi phần tử mẹ.

Hiệu ứng chuyển đổi mặc định an toàn và có ý nghĩa

Định kiểu cho phần tử chú giải công cụ để 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 đổi

Đối với mỗi cạnh có thể hiển thị chú giải công cụ, nếu người dùng đồng ý với chuyển động, hãy định vị một chút thuộc tính translateX bằng cách cho phép thuộc tính này di chuyển một khoảng nhỏ 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 đây là việc thiết lập trạng thái "out" (ngoài) vì trạng thái "in" (trong) nằm ở translateX(0).

JavaScript

Theo tôi, bạn không bắt buộc phải sử dụng JavaScript. Lý do là bạn không cần phải đọc bất kỳ chú giải công cụ nào trong số này để hoàn thành một tác vụ trong giao diện người dùng. Vì vậy, nếu chú giải công cụ hoàn toàn không hoạt động, thì đó không phải là vấn đề lớn. Điều này cũng có nghĩa là chúng ta có thể coi chú giải công cụ là được nâng cao 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ể biến mất hoàn toàn.

Tập lệnh polyfill thực hiện hai 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 khả năng hỗ trợ :has():

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 tên lớp cho các phần tử đó để sử dụng:

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 tập hợp các kiểu sử dụng lớp tên đó, mô phỏng bộ chọn :has() cho 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ẽ hiển thị chú giải công cụ nếu :has() không được hỗ trợ.

Kết luận

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

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 bản minh hoạ, gửi đường liên kết cho tôi trên Twitter và tôi sẽ thêm bản minh hoạ đó vào phầ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.

Tài nguyên