Tooltip yang Menyesuaikan Posisi

Saat membuat tooltip atau popover dengan Penempatan Anchor CSS, browser dapat otomatis "membalik" elemen ke posisi pengganti jika elemen tersebut akan meluap dari area pandang. Jika hal ini terjadi, Anda mungkin ingin menyesuaikan gaya konten yang diposisikan, misalnya untuk memosisikan ulang panah yang mengarah dari konten yang diposisikan ke anchor.

Kueri Penampung Tertaut mengatasi masalah ini dengan memungkinkan Anda mengkueri status pemosisian aktif elemen dan menerapkan gaya yang sesuai. Untuk pemosisian dropdown dan flyout umum yang ditambatkan dengan pembalikan tabrakan area pandang (tanpa penataan ulang panah arah), lihat Dropdown yang Memperhitungkan Area Pandang.

Permasalahan

Bayangkan tooltip yang muncul di atas anchor-nya secara default. Tombol ini memiliki panah "bawah" di bagian bawah. Jika pengguna men-scroll dan tooltip berputar untuk muncul di bawah anchor, panah kini mengarah ke arah yang salah dan berada di sisi tooltip yang salah.

Solusi: Kueri Penampung yang Ditambatkan

Dengan menetapkan container-type: anchored pada elemen yang diposisikan, Anda mengubahnya menjadi penampung kueri yang mengetahui status posisi anchor-nya sendiri. Kemudian, Anda dapat menggunakan kueri @container anchored() untuk memperbarui turunan atau elemen semunya.

1. Membuat tooltip dan pemicu

Menggunakan Popover API untuk membuat tooltip. Memanggil popover melalui popovertarget akan otomatis membuat koneksi anchor implisit dengan tombol pemicu, sehingga tidak diperlukan anchor-name atau position-anchor eksplisit.

<button popovertarget="tooltip" id="anchor" aria-describedby="tooltip">anchor</button>
<div id="tooltip" popover role="tooltip"></div>

Reset gaya inset dan margin popover untuk digunakan dengan pemosisian anchor, tetapi hanya jika pemosisian anchor didukung.

@supports (anchor-name: --my-anchor) {
  [popover] {
    inset: auto;
    margin: unset;
  }
}

2. Menyiapkan container

Terapkan container-type: anchored ke elemen yang diposisikan. Elemen ini juga harus memiliki position-try-fallbacks yang ditentukan untuk mengaktifkan perilaku pembalikan.

#tooltip {
  position: fixed;
  position-area: block-start;
  position-try-fallbacks: flip-block;

  /* Enable anchored container queries */
  container-type: anchored;
}

3. Gaya berdasarkan penggantian

Gunakan @container anchored(fallback: <value>) untuk menerapkan gaya saat penggantian tertentu aktif.

Seperti semua kueri penampung, @container hanya dapat menata gaya turunan penampung. Strategi umum untuk membuat panah adalah dengan elemen semu ::before dan ::after, yang diperlakukan sebagai turunan dan dapat diberi gaya secara langsung. Namun, untuk menata gaya tooltip itu sendiri (seperti yang terlihat di langkah 4), kita akan menambahkan elemen turunan ke tooltip, dan membuat panah di elemen semu ::before-nya.

<div id="tooltip" popover role="tooltip">
  <div class="tooltip-content">Tooltip</div>
</div>
.tooltip-content::before {
  /* Default "down" arrow for the 'top' position */
  content: "▼";
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 1rem;
}

/* Update to an "up" arrow when the 'flip-block' fallback (bottom) is active */
@container anchored(fallback: flip-block) {
  .tooltip-content::before {
    content: "▲";
    inset-block-start: 0;
    inset-block-end: auto;
  }
}

4. Menata gaya penampung itu sendiri

Jika Anda perlu mengubah properti pada penampung itu sendiri (seperti margin atau background-color) saat penampung dibalik, Anda harus menggunakan elemen wrapper dalam.

  1. Terapkan container-type: anchored ke elemen yang diposisikan di luar.
  2. Targetkan elemen dalam di dalam blok @container.
@container anchored(fallback: flip-block) {
  .tooltip-content {
    border-radius: 0 0 .5rem .5rem;
    margin-block-start: 0.25rem;
  }
}

Praktik terbaik

  • Pilih penggantian logis: Gunakan kata kunci seperti flip-block dan flip-inline di position-try-fallbacks untuk kueri yang lebih sederhana yang menangani RTL dan mode penulisan yang berbeda secara otomatis.
  • Gunakan elemen semu untuk panah: Panah tooltip murni bersifat dekoratif dan merupakan kandidat yang tepat untuk ::before atau ::after, yang dapat diberi gaya melalui kueri penampung yang ditambatkan tanpa DOM tambahan.

Strategi penggantian

Memosisikan panah berdasarkan penggantian yang diterapkan adalah progressive enhancement, dan tidak ada cara lain untuk bereaksi terhadap posisi penggantian. Untuk menyembunyikan panah di browser yang tidak mendukung kueri penampung posisi anchor, uji dukungan CSS dengan @supports (container-type: anchored).

@supports (container-type: anchored) {
  .tooltip-content::before {
    content: "▼";
  }
}

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.

Browser yang tidak mendukung Popover API juga tidak mendukung pemosisian anchor, sehingga tooltip akan muncul di tengah layar.