dialog
Marque un conteneur comme une boîte de dialogue modale ou non modale. Utilisez l'élément natif <dialog> avec showModal() — il gère nativement le piège de focus, le top-layer, le backdrop et la fermeture via Échap. Recourez à role="dialog" uniquement quand l'élément natif est impossible.
Quand l’utiliser
Utilisez <dialog> ouvert via .showModal(). L’élément natif est pris en charge par tous les navigateurs actuels ; il gère l’arrière-plan inerte, le piège de focus, la fermeture par Échap, le hook de style ::backdrop et le rendu en top-layer. Il vous épargne environ 200 lignes de JavaScript fragile.
Recourez à role="dialog" sur un <div> uniquement dans les cas suivants :
- Vous supportez des navigateurs antérieurs à Chrome 37 / Firefox 98 / Safari 15.4 (peu probable en 2026).
- Le design impose une boîte de dialogue qui ne peut pas vivre dans le top-layer (rare).
- Vous corrigez une modale personnalisée inaccessible lors d’un refactoring.
Toute boîte de dialogue DOIT avoir un nom accessible (aria-labelledby pointant vers un titre visible est le pattern le plus solide). Les dialogues modaux nécessitent également aria-modal="true".
Contrat clavier + focus
Selon le pattern APG dialog (modal) :
- À l’ouverture, le focus se déplace vers le premier élément focusable à l’intérieur du dialogue (souvent le bouton de fermeture ou le champ principal).
- Tab et Shift+Tab font circuler le focus DANS le dialogue — un « piège de focus ». Tab depuis le dernier élément revient au premier ; Shift+Tab depuis le premier revient au dernier.
- Échap ferme le dialogue.
- À la fermeture, le focus retourne sur l’élément qui a ouvert le dialogue. Sauvegarder et restaurer le focus est non négociable ; les utilisateurs qui perdent leur position n’ont plus de repère.
- Le reste de la page est
inert(ouaria-hidden="true"+ non-focusable en solution de repli) pendant que le dialogue est ouvert.
Erreurs courantes
- Boîte de dialogue personnalisée sans piège de focus. Tab sort du dialogue et passe derrière lui ; les utilisateurs perdent le contexte.
- Focus non restauré sur le déclencheur à la fermeture. Le prochain Tab atterrit sur le corps du document.
- Le contenu en arrière-plan reste accessible via Tab même s’il est visuellement masqué derrière le dialogue.
- Absence de nom accessible. Le dialogue s’ouvre et le lecteur d’écran annonce uniquement « dialog ».
- Boîte de dialogue personnalisée sans
aria-modal="true"— les technologies d’assistance la traitent comme du contenu en ligne. - Échap ferme le dialogue, mais celui-ci est rendu via un portail qui perd le focus clavier pendant l’animation de fermeture.
Exemple
<!-- Préféré -->
<dialog id="confirm">
<h2>Supprimer ce brouillon ?</h2>
<p>Cette action est irréversible.</p>
<form method="dialog">
<button value="cancel">Annuler</button>
<button value="delete" autofocus>Supprimer</button>
</form>
</dialog>
<script>
document.getElementById('confirm').showModal();
</script>
<!-- Quand <dialog> est impossible -->
<div role="dialog" aria-modal="true" aria-labelledby="dlgTitle">
<h2 id="dlgTitle">Modifier le profil</h2>
…
</div>