Kartu pengarah memberikan pratinjau konten interaktif saat pengguna menunjukkan minat pada link (melalui pengarahan kursor atau fokus). Informasi ini ditampilkan kepada pengguna sebelum mereka membuka link, dan memberikan konten yang mereka butuhkan atau membantu memverifikasi bahwa link tersebut akan berisi konten yang mereka cari.
Jika Anda memerlukan tooltip teks biasa non-interaktif, bukan pratinjau link terstruktur, lihat Menampilkan tooltip saat mengarahkan kursor.
1. Memicu kartu informasi
Gunakan API Interest Invokers untuk memicu kartu informasi. Hal ini memastikan kartu muncul saat kursor diarahkan dan difokuskan, serta menangani pengkabelan aksesibilitas secara otomatis.
- Tambahkan atribut
popover="hint"ke penampung kartu Anda. Gunakanhintuntuk menghindari penutupan menu popover yang tidak terkait yang mungkin terbuka. - Tambahkan atribut
interestforke link pemicu, yang mengarah keidkartu.
<a href="/article" interestfor="article-preview">Article title</a>
<!-- The `id` must match the `interestfor` value on the trigger. -->
<div id="article-preview" popover="hint" class="hovercard">
<h2>The buzz on hummingbirds</h2>
<p class="byline">By Delphi Aguilar</p>
<div>
<img src="bird.jpg" alt="A vibrant hummingbird">
<p>Brief summary of the article...</p>
</div>
</div>
Anda tidak perlu menyertakan link tambahan ke konten di dalam kartu informasi, karena link tersebut sudah ada di link 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 implisittooltip. JANGAN tetapkanrole="tooltip"sendiri. - Pengaitan implisit: Browser secara implisit mengaitkan elemen sumber dengan target melalui
aria-describedbyjika targetnya adalah teks biasa, atau melaluiaria-detailsjika targetnya berisi konten interaktif. JANGAN menambahkanaria-describedbyatauaria-detailske pemicu. - Konten interaktif: Karena pengaitan beralih ke
aria-detailsjika diperlukan, target diizinkan untuk berisi konten interaktif (misalnya, link di dalam "kartu minat").
2. Penentuan Posisi dengan Anchor Positioning
Posisikan kartu pengarah relatif terhadap pemicunya menggunakan CSS Anchor Positioning. Saat menggunakan interestfor, pemicu akan menjadi anchor implisit untuk popover.
[popover].hovercard {
/* Position the card below the trigger, aligned with its inline-start edge
and spanning toward the inline-end, flipping if it overflows the viewport. */
position-area: block-end span-inline-end;
position-try-fallbacks: flip-block, flip-inline;
}
3. Menganimasikan masuk dan keluar
Secara default, minat ditampilkan dan hilang untuk pengguna keyboard dan mouse dengan penundaan setengah detik. Tindakan ini mencegah popover yang ditargetkan terbuka saat berpindah-pindah halaman atau menggerakkan mouse, dan menutup saat menggerakkan mouse dari pemicu ke popover. Untuk menyesuaikan pengaturan waktu, gunakan properti CSS interest-delay.
[interestfor]{
/* Shorthand for interest-delay-start and interest-delay-end */
interest-delay: 0.2s 0.1s;
}
Jika pengguna cenderung berpindah di antara beberapa pemicu secara berurutan, tetapkan penundaan awal ke 0s jika popover yang dipicu minat sudah terbuka.
:root:has(:interest-source) [interestfor] {
interest-delay-start: 0s;
}
Gunakan @starting-style untuk menentukan animasi masuk dan transition-behavior: allow-discrete (bersama dengan display dan overlay) untuk menganimasikan keluar dari lapisan atas, yang membatasi transisi di belakang @media (prefers-reduced-motion: no-preference).
[popover].hovercard {
opacity: 0;
transform-origin: top;
}
[popover].hovercard:popover-open {
opacity: 1;
transform: translateY(0) scale(1);
}
@starting-style {
[popover].hovercard:popover-open {
opacity: 0;
transform: translateY(-10px) scale(0.95);
}
}
/* MANDATORY: Respect user preference for reduced motion by selectively applying transitions. */
@media (prefers-reduced-motion: no-preference) {
[popover].hovercard {
transition:
opacity,
transform,
display,
overlay;
transition-duration: 0.4s;
transition-behavior: allow-discrete;
}
}
4. OPSIONAL: Berubah dengan mulus ke halaman berikutnya
Anda dapat menggunakan Transisi Tampilan Lintas Dokumen untuk membuat animasi "perubahan" yang lancar antara kartu informasi dan halaman tujuan. Lihat Transisi Lintas Dokumen yang Konsisten untuk mendapatkan panduan tentang penerapannya.
Dengan menetapkan nilai view-transition-name yang cocok ke elemen di kartu informasi dan padanannya di halaman berikutnya, browser akan menganimasikannya di seluruh navigasi. Anda dapat memberi nama beberapa elemen (misalnya judul, gambar, nama penulis) untuk membuat efek perubahan bentuk multi-elemen yang kompleks. Tetapkan view-transition-name ke elemen di popover yang terbuka menggunakan :popover-open, untuk menghindari pembuatan view-transition-name duplikat atau memerlukan view-transition-name khusus link.
/* Opt-in to cross-document transitions on both pages */
@view-transition {
navigation: auto;
}
/* Don't show transitions when loading this page */
::view-transition-group(*) {
animation-duration: 0s;
}
/* Assign names ONLY when the popover is open to ensure only the correct elements are selected. */
[popover]:popover-open {
view-transition-name: --hovercard;
view-transition-class: morph;
h2 {
view-transition-name: --title;
view-transition-class: morph;
}
img {
view-transition-name: --image;
view-transition-class: morph;
}
}
WAJIB: Untuk memastikan transisi stabil dan tidak berkedip, halaman tujuan harus menggunakan blocking="render" dan <link rel="expect"> untuk menunggu konten penting diuraikan sebelum merender frame pertama.
<!-- On the destination page: -->
<head>
<!-- Block rendering until the hero image and title are parsed,
ensuring the view transition snapshot is taken at the right time. -->
<link rel="expect" href="#main-content" blocking="render">
</head>
<body>
<main id="main-content">
<h1>The buzz on hummingbirds</h1>
<img src="bird.jpg">
</main>
</body>
/* On the destination page: */
main {
view-transition-name: --hovercard;
view-transition-class: morph;
}
h1 {
view-transition-name: --title;
view-transition-class: morph;
}
img {
view-transition-name: --image;
view-transition-class: morph;
}
/* By default no transition */
::view-transition-group(*) {
animation-duration: 0s;
}
/* Short transition for morphing elements */
::view-transition-group(.morph) {
animation-duration: 0.4s;
}
/* Disable transition if no `old` view */
::view-transition-new(.morph):only-child {
animation-duration: 0s;
}
Strategi penggantian
Karena pemicunya adalah link <a href="..."> standar, browser yang tidak mendukung masih dapat membuka link saat diklik jika Anda memilih untuk memperlakukan hovercard sebagai progressive enhancement. Jika dukungan hovercard lintas browser diperlukan, muat polyfill secara kondisional sesuai kebutuhan.
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.
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-sourcedan:interest-targetyang sebenarnya, sehingga menerapkan class.interest-sourcedan.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, daninterest-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);
}