Menampilkan tooltip saat mengarahkan kursor

Pengguna berharap dapat melihat informasi terkait tambahan tanpa mengubah konteksnya sepenuhnya. Menampilkan tooltip saat pengguna tertarik untuk mendapatkan informasi lebih lanjut dapat berguna untuk memberikan definisi istilah, memperjelas tindakan yang akan dilakukan tombol khusus ikon, atau memberikan panduan kolom formulir tambahan.

Membuat tooltip

Anda dapat membuat popover dengan perilaku yang diperlukan dengan menambahkan atribut popover="hint" ke <div> atau elemen lain yang sesuai secara semantik. Saat pengguna membuka tooltip, tindakan ini akan menyembunyikan tooltip popover="hint" lainnya, tetapi tidak menyembunyikan tooltip auto atau manual. Fungsi ini juga menangani penutupan tooltip bertingkat.

Elemen ini juga memberikan perilaku tutup ringan, sehingga saat pengguna mengklik atau memfokuskan di luar popover, popover akan ditutup.

Elemen tooltip harus memiliki atribut id dengan nilai unik:

<!-- 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>

Pengguna menunjukkan minat pada informasi tambahan dengan mengarahkan kursor atau memfokuskan pada elemen <a> atau <button>. Elemen harus memiliki atribut interestfor yang cocok dengan atribut id tooltip.

<!-- 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>

Pemicu harus memiliki indikator visual untuk menunjukkan bahwa ada informasi tambahan yang tersedia dengan berinteraksi dengan pemicu.

Aksesibilitas bawaan di interestfor

Saat Anda menggunakan interestfor, browser akan menangani pengaitan teknologi pendukung untuk Anda:

  • Semantik implisit: Target dengan popover="hint" mendapatkan peran minimum implisit tooltip. JANGAN tetapkan role="tooltip" sendiri.
  • Pengaitan implisit: Browser secara implisit mengaitkan elemen sumber dengan target melalui aria-describedby jika targetnya adalah teks biasa, atau melalui aria-details jika targetnya berisi konten interaktif. JANGAN menambahkan aria-describedby atau aria-details ke pemicu.
  • Konten interaktif: Karena pengaitan beralih ke aria-details jika diperlukan, target diizinkan untuk berisi konten interaktif (misalnya, link di dalam "kartu minat").

Batasan Aksesibilitas (WCAG 1.4.13)

Meskipun interestfor menangani semantik di atas, penerapan Anda harus tetap memenuhi WCAG 1.4.13 (Konten saat Diarahkan atau Difokuskan):

  • Dapat ditutup: Pengguna harus dapat menutup tooltip tanpa memindahkan kursor atau fokus keyboard (misalnya, dengan menekan tombol Escape). Atribut popover native mengelola binding ini secara otomatis.
  • Dapat diarahkan: Penunjuk harus dapat bergerak di atas konten tooltip itu sendiri tanpa menghilangkan tooltip. Hal ini memungkinkan pengguna dengan alat pembesaran membaca teks tooltip dengan aman.
  • Persisten: Tooltip harus tetap terlihat hingga pemicu pengarahan kursor atau fokus dihapus, pengguna menutupnya secara eksplisit, atau kontennya tidak lagi valid.

Memosisikan tooltip

Tooltip diposisikan menggunakan CSS Anchor Positioning. Saat tooltip dibuka menggunakan interestfor, elemen pemicu akan otomatis menjadi anchor implisit untuk popover.

Di browser modern yang mendukung pemosisian anchor native, Anda tidak perlu menentukan anchor-name pada pemicu atau position-anchor pada tooltip. Anda dapat memosisikan tooltip secara langsung relatif terhadap anchor implisitnya menggunakan position-area dan menangani pembalikan tabrakan dengan 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;
}

Strategi penggantian

Penggantian & dukungan browser untuk Interest invoker

Pemanggil minat harus di-polyfill secara bersyarat menggunakan paket polyfill interestfor dari NPM. Lebih baik memaketkan polyfill daripada menggunakan CDN.

WAJIB: Deteksi fitur dengan memeriksa properti interestForElement di HTMLButtonElement.prototype, dan muat polyfill hanya jika dukungan native tidak ada.

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

Peringatan Polyfill CSS

Saat menggunakan polyfill, CSS API sedikit berubah untuk memperhitungkan kurangnya dukungan properti dan pseudo-class native:

  • Pseudo-class: Polyfill tidak dapat menentukan pseudo-class :interest-source dan :interest-target yang sebenarnya, sehingga menerapkan class .interest-source dan .interest-target. WAJIB: Gabungkan dengan :is() untuk mendukung status native dan polyfill.
/* Styles to apply when the effect is being previewed */
:is(:interest-source, .interest-source) { /* ... */ }
:is(:interest-target, .interest-target) { /* ... */ }
  • Properti CSS: Untuk interest-delay, interest-delay-start, dan interest-delay-end, polyfill memerlukan penggunaan variabel CSS karena tidak dapat membaca properti kustom secara langsung di semua browser.
/* 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);
}

Penggantian & dukungan browser untuk Popover

Popover API sebagian besar merupakan progressive enhancement, tetapi perilaku penentuannya — promosi lapisan atas, penutupan ringan, dan pemanggilan popovertarget — tidak memiliki padanan khusus CSS. Browser lama memerlukan polyfill, atau penggantian manual jika Anda tidak ingin mengirimkannya.

Polyfill: Untuk mendukung atribut popover di browser lama, muat @oddbird/popover-polyfill secara bersyarat. WAJIB: Deteksi fitur dengan memeriksa properti popover di HTMLElement.prototype, dan muat polyfill hanya jika dukungan native tidak ada — JANGAN memuatnya tanpa syarat.

Dengan bundler atau peta impor:

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

Tanpa bundler, impor dari CDN di dalam <script type="module">:

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

Peringatan gaya: Polyfill tidak dapat menentukan pseudo-class :popover-open yang sebenarnya, sehingga menerapkan class .\:popover-open. WAJIB: Gabungkan keduanya dengan :is() atau :where(). Jika tidak, browser yang tidak memiliki :popover-open akan menghapus seluruh aturan:

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

Atau, untuk penggantian lama tanpa polyfill, gunakan position: fixed dan hitung koordinat secara manual melalui getBoundingClientRect() atau andalkan pemosisian default dengan inset: auto jika hal itu dapat diterima untuk kasus penggunaan.

popover-polyfill tidak melakukan polyfill pada perilaku petunjuk di browser yang mendukung popover, tetapi tidak mendukung popover="hint". Untuk browser tersebut, tooltip yang dibuka melalui fokus dapat tetap terbuka saat tooltip kedua dibuka melalui pengarahan kursor.

Untuk mendukung browser tanpa pemosisian anchor, Anda dapat menggunakan polyfill @oddbird/css-anchor-positioning. Atau, Anda dapat menggunakan @supports untuk menentukan posisi penggantian.

Saat menggunakan polyfill @oddbird/css-anchor-positioning untuk dukungan browser lama, perlu diketahui bahwa polyfill tidak mendukung anchor implisit atau position-area pada popover. Tetapkan anchor-name secara eksplisit pada pemicu, tetapkan position-anchor pada popover, dan posisikan menggunakan fungsi inset anchor(), bukan 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;
}