Een dialoogvenster sluiten door ernaast te klikken

Webfuncties: <dialog closedby>

Moderne modale dialoogvensters ondersteunen vaak 'light-dismiss', waardoor gebruikers een dialoogvenster kunnen sluiten door op de achtergrond (het gebied buiten het dialoogvenster) te klikken of te tikken. Het kenmerk closedby biedt een declaratieve manier om dit gedrag aan te zetten zonder aangepaste JavaScript.

Implementatie

Zo zet je licht sluiten aan:

  1. Voeg closedby="any" toe aan het element <dialog>.
  2. Open het dialoogvenster met dialog.showModal().

Kenmerkwaarden

  • any: Maakt licht sluiten (klikken op de achtergrond), sluitingsverzoeken (de Esc-toets) en ontwikkelaarsmechanismen (bijv. dialog.close()) mogelijk.
  • closerequest: Hiermee worden alleen sluitingsverzoeken en ontwikkelaarsmechanismen aangezet. Dit is de standaardinstelling voor modale dialoogvensters.
  • none: Alleen ontwikkelaarsmechanismen kunnen het dialoogvenster sluiten.

De Backdrop vormgeven

Als een dialoogvenster wordt geopend als een modaal venster met showModal(), genereert de browser een pseudo-element ::backdrop. Deze achtergrond bedekt het hele weergavegebied en bevindt zich direct achter het dialoogvenster.

/* 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 */
}

Voorbeeld

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

Beperkingen en toegankelijkheid

  • VERPLICHT: Gebruik closedby="any" om sluiten door te klikken declaratief aan te zetten.
  • VERPLICHT: Open modale dialoogvensters altijd met showModal(). Zo zorg je dat het dialoogvenster zich in de bovenste laag bevindt, de focus wordt vastgehouden en de Esc-toets wordt verwerkt.
  • WEL: Gebruik aria-labelledby of aria-label om een toegankelijke naam voor het dialoogvenster te geven.
  • DO NOT: Use closedby for non-modal dialogs (opened with show()), as they do not have a backdrop and won't trigger light-dismiss.
  • DOE DIT NIET: Gebruik de gebeurtenis click voor kritieke logica die vóór het sluiten moet plaatsvinden. Luister in plaats daarvan naar de gebeurtenissen close of cancel.

Reservestrategieën

VERPLICHT: Voor browsers die nog geen ondersteuning bieden voor closedby, moet je een fallback voor licht sluiten implementeren door met het volgende script te controleren of er buiten de grenzen van de dialoogvenstercontent is geklikt:

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();
  });
}