Fermer une boîte de dialogue par simple clic

Fonctionnalités Web : <dialog closedby>

Les boîtes de dialogue modales modernes sont souvent compatibles avec la fermeture par clic, ce qui permet aux utilisateurs de fermer une boîte de dialogue en cliquant ou en appuyant sur l'arrière-plan (la zone située en dehors de la boîte de dialogue). L'attribut closedby permet d'activer ce comportement de manière déclarative sans JavaScript personnalisé.

Implémentation

Pour activer la fermeture par clic :

  1. Ajoutez closedby="any" à l'élément <dialog>.
  2. Ouvrez la boîte de dialogue à l'aide de dialog.showModal().

Valeurs des attributs

  • any : active la fermeture par clic (clic sur l'arrière-plan), les "demandes de fermeture" (touche Esc) et les mécanismes de développement (par exemple, dialog.close()).
  • closerequest : active uniquement les "demandes de fermeture" et les mécanismes de développement. Il s'agit de la valeur par défaut pour les boîtes de dialogue modales.
  • none : seuls les mécanismes de développement peuvent fermer la boîte de dialogue.

Styliser l'arrière-plan

Lorsqu'une boîte de dialogue est ouverte en tant que fenêtre modale à l'aide de showModal(), le navigateur génère un pseudo-élément ::backdrop. Cet arrière-plan couvre l'intégralité de la fenêtre d'affichage et se trouve directement derrière la boîte de dialogue.

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

Exemple

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

Contraintes et accessibilité

  • OBLIGATOIRE : Utilisez closedby="any" pour activer la fermeture par clic en dehors de l'élément de manière déclarative.
  • OBLIGATOIRE : Ouvrez toujours les boîtes de dialogue modales avec showModal(). Cela garantit que la boîte de dialogue se trouve dans la couche supérieure, que la sélection est piégée et que la touche Esc est gérée.
  • À FAIRE : Utilisez aria-labelledby ou aria-label pour fournir un nom accessible à la boîte de dialogue.
  • À ÉVITER : Utiliser closedby pour les boîtes de dialogue non modales (ouvertes avec show()), car elles n'ont pas d'arrière-plan et ne déclenchent pas de fermeture par clic en dehors de la boîte de dialogue.
  • À ÉVITER : Utiliser l'événement click pour une logique critique qui doit se produire avant la fermeture. Écoutez plutôt les événements close ou cancel.

Stratégies de remplacement

OBLIGATOIRE : Pour les navigateurs qui ne sont pas encore compatibles avec closedby, vous devez implémenter une solution de remplacement pour la fermeture par clic en dehors de la boîte de dialogue en vérifiant si un clic s'est produit en dehors des limites du contenu de la boîte de dialogue à l'aide du script suivant :

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