Menutup Dialog dengan Cepat

Fitur web: <dialog closedby>

Dialog modal modern sering kali mendukung "penutupan ringan", yang memungkinkan pengguna menutup dialog dengan mengklik atau mengetuk latar belakang (area di luar dialog). Atribut closedby menyediakan cara deklaratif untuk mengaktifkan perilaku ini tanpa JavaScript kustom.

Penerapan

Untuk mengaktifkan penutupan ringan:

  1. Tambahkan closedby="any" ke elemen <dialog>.
  2. Buka dialog menggunakan dialog.showModal().

Nilai Atribut

  • any: Mengaktifkan penutupan ringan (mengklik latar belakang), "permintaan tutup" (tombol Esc), dan mekanisme developer (misalnya, dialog.close()).
  • closerequest: Hanya mengaktifkan "permintaan tutup" dan mekanisme developer. Ini adalah setelan default untuk dialog modal.
  • none: Hanya mekanisme developer yang dapat menutup dialog.

Menata Gaya Backdrop

Saat dialog dibuka sebagai modal menggunakan showModal(), browser akan membuat elemen pseudo ::backdrop. Backdrop ini menutupi seluruh area pandang dan berada tepat di belakang dialog.

/* Style the backdrop to indicate the dialog is modal */
dialog::backdrop {
  background-color: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(2px); /* Optional: add blur for modern browsers */
}

Contoh

<!-- MANDATORY: Use closedby="any" to enable light-dismiss behavior -->
<dialog id="myDialog" closedby="any" aria-labelledby="dialogTitle">
  <form method="dialog">
    <h2 id="dialogTitle">Feedback</h2>
    <p>Click outside this box or press Esc to dismiss.</p>
    <button type="submit">Close</button>
  </form>
</dialog>

<button onclick="document.getElementById('myDialog').showModal()">Open Dialog</button>

Batasan & Aksesibilitas

  • WAJIB: Gunakan closedby="any" untuk mengaktifkan penutupan ringan secara deklaratif.
  • WAJIB: Selalu buka dialog modal dengan showModal(). Hal ini memastikan dialog berada di lapisan atas, fokus terjebak, dan tombol Esc ditangani.
  • LAKUKAN: Gunakan aria-labelledby atau aria-label untuk memberikan label aksesibilitas untuk dialog.
  • JANGAN: Gunakan closedby untuk dialog non-modal (dibuka dengan show()), karena tidak memiliki latar belakang dan tidak akan memicu penutupan ringan.
  • JANGAN: Menggunakan peristiwa click untuk logika penting yang seharusnya terjadi sebelum penutupan; sebagai gantinya, proses peristiwa close atau cancel.

Strategi penggantian

WAJIB: Untuk browser yang belum mendukung closedby, Anda harus menerapkan penggantian untuk penutupan ringan dengan memeriksa apakah klik terjadi di luar batas konten dialog menggunakan skrip berikut:

const dialog = document.querySelector('dialog');

// Fallback for browsers without closedby support
if (!('closedBy' in HTMLDialogElement.prototype)) {
  dialog.addEventListener('click', (event) => {
    // 1. When clicking the backdrop, the event target is the dialog element itself.
    // Ignore clicks where the target is a child element inside the dialog.
    if (event.target !== dialog) return;

    // 2. Check if the click coordinates fall within the dialog's content box.
    // This distinguishes between a click on the backdrop vs a click on the dialog's background/padding.
    const rect = dialog.getBoundingClientRect();
    const isDialogContent = (
      rect.top <= event.clientY &&
      event.clientY <= rect.top + rect.height &&
      rect.left <= event.clientX &&
      event.clientX <= rect.left + rect.width
    );

    if (isDialogContent) return;

    // 3. Since the click was outside the content area (on the backdrop), manually close the dialog.
    dialog.close();
  });
}