Topik wawancara representatif

Wawancara Frontend: Merancang Popover HTML yang Aksesibel

FrontendSedang
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Rancang permukaan filter non-modal yang dibuka oleh sebuah tombol: mengeklik di luar atau menekan tombol Escape akan menutupnya, pemicu dan permukaan tetap aksesibel, serta beberapa permukaan tidak boleh saling menutup secara tidak sengaja. Bagaimana Anda akan menggunakan HTML Popover API, dan di mana batasannya dengan dialog modal?

Konteks dan cakupan

Ini adalah masalah interaksi aksesibilitas dan Web Platform modern. Tujuannya adalah membuat menu, panel filter, atau permukaan bantuan yang membiarkan halaman tetap dapat digunakan sambil mendukung light-dismiss. HTML Popover API menggunakan popover, popovertarget, dan top layer untuk menyediakan siklus hidup tampilan yang dikelola browser. Jangan memigrasikan setiap overlay ke API native; pemosisian itu sendiri bukanlah latihan utama.

Hal yang diuji oleh pewawancara

  • Membedakan popover="auto", popover="manual", dan semantik dialog modal.
  • Menjaga pemicu, permukaan, dan aksi penutupan tetap dapat dipahami secara semantik.
  • Menangani tombol Escape, klik di luar, beberapa permukaan, pengembalian fokus, dan event siklus hidup.
  • Menjelaskan progressive enhancement, dukungan browser, dan fallback yang tidak merusak sistem.

Klarifikasi yang perlu ditanyakan terlebih dahulu

Konfirmasikan apakah latar belakang tetap interaktif. Jika harus diblokir, gunakan <dialog> dengan showModal() daripada popover. Perjelas apakah hanya satu permukaan yang boleh terbuka, apakah beberapa permukaan manual dapat berdampingan, apakah pemicu berfungsi sebagai toggle, apakah pengiriman formulir yang berhasil akan menutupnya, dan jangkauan browser minimum. Permukaan filter biasanya non-modal, tetapi pengguna keyboard tetap memerlukan alur fokus dan penutupan yang eksplisit.

Jawaban 30 detik

Mulailah dengan HTML semantik: tempatkan popovertarget pada pemicu dan popover="auto" pada permukaan; gunakan manual hanya untuk orkestrasi penutupan kustom. Browser menyediakan perilaku top-layer, Escape, dan light-dismiss luar. Saya menambahkan entri fokus, pengembalian fokus, teks status, dan penanganan siklus hidup beforetoggle/toggle. Browser yang tidak didukung mempertahankan DOM dan nama yang sama dengan polyfill kecil daripada menggunakan penangan klik global yang dapat menutup permukaan yang tidak terkait.

Solusi langkah demi langkah

1. Memilih popover atau dialog modal

Popover cocok untuk menu, filter, bantuan non-pemblokir, dan tindakan sementara; halaman tetap non-modal. <dialog> dengan showModal() cocok untuk konfirmasi, pembayaran, atau peringatan yang harus ditangani terlebih dahulu karena menyediakan semantik modal dan memblokir latar belakang. Keduanya dapat menggunakan top layer, tetapi nama aksesibel, strategi fokus, dan alasan penutupannya berbeda; mengganti dialog dengan atribut popover bukanlah hal yang setara.

2. Membangun hubungan antara pemicu dan permukaan

Struktur semantik terkecil memungkinkan browser mempertahankan hubungan target:

html
<button type="button" popovertarget="filters" aria-controls="filters">
  Filters
</button>
<div id="filters" popover="auto">
  <form method="get">
    <label>Status <select name="status"><option>All</option></select></label>
    <button type="submit">Apply</button>
  </form>
</div>

popovertarget menjadikan tombol sebagai pemicu deklaratif, dan browser mengelola hubungan tersebut selama proses buka dan tutup. aria-controls dapat membantu teknologi asistif memahami hubungan tersebut, tetapi tidak menggantikan nama yang terlihat atau perilaku fokus yang benar. Komponen yang kompleks harus mempertahankan referensi pemicu dalam skrip dan mengembalikan fokus kepadanya hanya jika pemicu tersebut masih ada dan dapat menerima fokus.

3. Memahami auto, manual, dan light-dismiss

Popover auto mendukung light-dismiss yang dikelola browser: tombol Escape atau klik di luar dapat menutupnya, dan popover ini berpartisipasi dalam rantai penutupan otomatis. Popover manual tidak ditutup oleh mekanisme tersebut; panggil showPopover(), hidePopover(), atau togglePopover() secara eksplisit. Gunakan ini saat beberapa permukaan dapat berdampingan atau siklus hidupnya bersifat kustom. Jangan menambahkan penutupan klik tingkat dokumen di atas auto; permukaan bersarang dan klik pemicu dapat saling berbenturan.

4. Menangani top layer, pemosisian, dan backdrop

Setelah terbuka, popover masuk ke top layer dan tidak lagi dibatasi oleh konteks penumpukan overflow atau z-index milik elemen leluhur biasa. Gunakan CSS Anchor Positioning atau tata letak reguler untuk penempatan, dengan fallback statis saat penempatan gagal. Popover non-modal sebaiknya tidak secara otomatis menerima backdrop layar penuh; jika produk memerlukannya, periksa kembali apakah persyaratannya sebenarnya adalah perilaku dialog modal. Top layer mengubah urutan rendering tetapi tidak menyelesaikan masalah viewport sempit, kontainer scroll, atau penempatan saat terjadi tabrakan (collision).

5. Menentukan fokus dan perilaku keyboard

Pindahkan fokus ke kontrol pertama yang dapat ditindaklanjuti, atau pertahankan default browser hanya setelah mengujinya. Pada tombol Escape, kembalikan fokus ke pemicu; jika pemicu telah dihapus, alihkan ke konteks terlihat terdekat. Urutan tab harus menelusuri permukaan secara alami; jangan sembunyikan semua kontrol dengan tabindex="-1". Popover mirip menu memerlukan tombol panah item menu dan semantik pemilihan, sedangkan formulir filter harus mempertahankan perilaku keyboard formulir biasa.

6. Mengamati siklus hidup daripada menebak status global

Gunakan beforetoggle untuk memvalidasi transisi, mencatat alasan penutupan, atau menyinkronkan status aplikasi; gunakan toggle setelah status benar-benar berubah untuk memperbarui label dan fokus. Daftarkan penangan per elemen dan bersihkan saat komponen dihancurkan. Untuk permukaan auto yang saling eksklusif, andalkan tumpukan penutupan browser daripada mempertahankan ID terbuka global yang usang.

7. Mengoordinasikan pengiriman formulir dan status aplikasi

Setelah pengiriman filter berhasil, panggil hidePopover() secara eksplisit jika diinginkan, tetapi jangan anggap penutupan sebagai bukti keberhasilan. Pada permintaan yang gagal, biarkan permukaan tetap terbuka dan kaitkan pesan kesalahan dengan formulir. Status terbuka adalah status UI sementara; nilai filter adalah status bisnis. Pisahkan keduanya, dan hitung ulang pada perubahan navigasi atau riwayat daripada memperlakukan :popover-open sebagai satu-satunya sumber kebenaran.

8. Menggunakan progressive enhancement dan menguji interaksi

Lakukan deteksi fitur pada API sebenarnya, seperti HTMLElement.prototype.showPopover. Gunakan perilaku native jika tersedia; jika tidak, pertahankan pemicu, konten, dan nama aksesibel yang sama dengan polyfill kecil untuk tampilan, Escape, klik di luar, dan pengembalian fokus. Uji keyboard, sentuhan, zoom, scrolling, permukaan bersarang, pemicu yang dihapus, formulir yang gagal, dan pengurangan gerakan (reduced motion). Verifikasi nama, status, dan kesalahan dengan pembaca layar daripada hanya memeriksa piksel saja.

Jawaban model

Saya akan mendefinisikan ini sebagai popover filter non-modal, bukan dialog. Tombol menggunakan popovertarget dan panel menggunakan popover="auto"; browser mengelola top layer, Escape, dan light-dismiss luar, sementara skrip menangani status formulir, pengembalian fokus, dan event siklus hidup. Saat terbuka, fokus masuk ke kontrol pertama; saat ditutup, fokus kembali ke pemicu. Pengiriman yang gagal membuat permukaan tetap terbuka dan menampilkan kesalahan; pengiriman yang berhasil dapat menutupnya. Gunakan manual hanya saat beberapa permukaan kustom harus berdampingan, dan jangan menduplikasi penanganan klik dokumen untuk auto. Sediakan fallback penempatan statis dan polyfill semantik saat deteksi fitur gagal. Uji alur keyboard, sentuhan, scroll, dan teknologi asistif.

Kesalahan umum

  • Menggunakan popover untuk konfirmasi yang harus memblokir latar belakang, sehingga kehilangan semantik modal.
  • Menambahkan penutupan klik dokumen pada auto, yang dapat menutup permukaan bersarang atau kontrol pengiriman.
  • Mengubah display tanpa mempertahankan hubungan pemicu, pengembalian fokus, atau status kesalahan.
  • Mensimulasikan dialog dengan backdrop layar penuh sambil mempertahankan perilaku non-modal.
  • Memperlakukan top layer sebagai pemosisian otomatis dan mengabaikan scrolling, viewport sempit, dan fallback tabrakan.
  • Menutup formulir yang gagal tanpa syarat sehingga pengguna tidak dapat melihat atau memperbaiki kesalahan.
  • Hanya menguji klik mouse dan melewatkan perilaku Escape, Tab, sentuhan, dan pembaca layar.

Pertanyaan lanjutan

Kapan sebaiknya Anda menggunakan <dialog>?

Gunakan <dialog> dengan showModal() saat latar belakang harus inert, pengguna harus membuat keputusan terlebih dahulu, atau perilaku fokus modal diperlukan. Light-dismiss dan semantik non-modal Popover tidak dapat menggantikan pemblokiran latar belakang serta tindakan batal/konfirmasi yang eksplisit.

Bagaimana cara membuat beberapa permukaan filter saling eksklusif?

Pilihlah auto untuk permukaan yang saling eksklusif agar browser mengelola rantai penutupan. Jika beberapa permukaan manual dapat berdampingan, pertahankan set instans yang eksplisit, tutup hanya instans yang ditargetkan, dan simpan pemicu serta pengembalian fokus setiap instans secara terpisah.

Bagaimana cara mendukung browser tanpa Popover API?

Lakukan deteksi fitur pada API dan pertahankan DOM serta atribut semantik yang sama, dengan polyfill untuk tampilan, perilaku penutupan, Escape, klik di luar, dan pengembalian fokus. Jangan menurunkan kualitas ke div berposisi absolut yang tidak bernama dan tidak dapat diakses keyboard; dokumentasikan matriks kompatibilitas dan uji sebelum rilis.

Bagaimana cara menguji batasan light-dismiss?

Uji klik pada pemicu, di dalam permukaan, elemen saudara di luar, kontainer scroll, dan popover lain. Klik internal harus tetap terbuka; klik eksternal hanya boleh menutup permukaan auto yang memenuhi syarat, dan klik pemicu berulang tidak boleh membuat status duplikat. Tambahkan pengujian Escape dan sentuhan.

Bisakah animasi merusak aksesibilitas?

Gunakan prefers-reduced-motion untuk mempersingkat atau menghapus transisi sambil menjaga fokus dan status yang dapat dibaca tetap konsisten. Jangan menyembunyikan kontrol yang dapat difokuskan hanya dengan opasitas; cegah pengiriman duplikat selama penutupan dan tampilkan perubahan status yang stabil ke teknologi asistif.

Bagaimana jika penempatan gagal?

Dengan anchor positioning, sediakan fallback alur normal atau aman-viewport dan tanggapi perubahan ukuran serta scroll. Kegagalan tidak boleh memotong konten atau mendorongnya keluar layar; formulir inti tetap dapat digunakan tanpa peningkatan pemosisian tersebut.

Sumber publik

Pertanyaan terkait