Bac à sable
La fenêtre modale
Sans gestion du focus, la personne qui navigue au clavier se retrouve derrière la fenêtre modale, dans une page qu'elle ne voit plus. L'élément dialog gère ce focus seul, et depuis décembre 2025 un bouton l'ouvre sans script dans tous les navigateurs récents.
- Technique
- dialog et command
- Navigateurs
- Chrome 135+, Firefox 144+, Safari 26.2+
- JavaScript
- Aucun, 5 lignes en repli
Démo
Anatomie
button command="show-modal"Le bouton d'ouverture, relié à la fenêtre parcommandfor.dialogLa fenêtre, placée au-dessus de toute la page.h2 autofocusLe titre, qui nomme la fenêtre et reçoit le focus à l'ouverture.- Contenu La phrase qui dit ce que la suppression entraîne.
form method="dialog"Les boutons Annuler et Supprimer, qui ferment la fenêtre sans script. Lavaluedu bouton choisi passe dansreturnValue.::backdropLe voile posé sur la page.
Code HTML
<!-- Élément déclencheur -->
<button
type="button"
commandfor="delete-dialog"
command="show-modal">
Supprimer le brouillon
</button>
<!-- Modale -->
<dialog id="delete-dialog" aria-labelledby="delete-dialog-title">
<!-- Titre : nomme la fenêtre, et autofocus y pose le focus à l'ouverture -->
<h2
id="delete-dialog-title"
tabindex="-1"
autofocus>
Supprimer ce brouillon ?
</h2>
<p>Le brouillon sera supprimé définitivement.</p>
<!-- Les 2 boutons ferment la fenêtre, puis le focus revient au déclencheur.
dialog.returnValue reçoit la value du bouton choisi -->
<form method="dialog">
<button value="cancel">Annuler</button>
<button value="delete">Supprimer</button>
</form>
</dialog>dialog::backdrop {
background: rgb(0 86 59 / 0.45);
}
/* La page ne défile plus derrière la fenêtre ouverte.
scrollbar-gutter garde la place de la barre : la page ne se décale pas */
html:has(dialog:modal) {
overflow: hidden;
scrollbar-gutter: stable;
}Usages
Recommandé pour
- Une action courte qui demande une réponse avant de continuer, comme confirmer une suppression.
- Un contenu qui n'a de sens qu'au moment où l'on clique sur le bouton.
Déconseillé pour
- Laisser la page défiler derrière la fenêtre. La molette ou le doigt fait bouger un contenu inerte, et on perd sa place à la fermeture :
html:has(dialog:modal)bloque le défilement, sans script. - Une fenêtre qui s'ouvre toute seule au chargement de la page.
- Un bouton Fermer en croix sans nom accessible.
<div role="dialog">à la place dedialog: il faut alors gérer le focus et Échap à la main.- Un contenu long, que l'on voudrait lire en gardant la page sous les yeux.
Accessibilité
Rôles et attributs ARIA
aria-labelledby est le seul attribut ARIA de la démo. Ouverte en mode modal, la fenêtre se passe d'aria-modal.
| Attribut | Élément | Description |
|---|---|---|
commandfor="delete-dialog" | button | Désigne la fenêtre à ouvrir par son id. Le bouton garde un nom qui dit ce qu'il déclenche : « Supprimer le brouillon ». |
command="show-modal" | button | Ouvre la fenêtre en mode modal, sans script. À la fermeture, le focus revient sur ce bouton. |
Rôle dialog (implicite) | dialog | Le lecteur d'écran reçoit une boîte de dialogue, modale puisque show-modal l'a ouverte. |
aria-labelledby="delete-dialog-title" | dialog | Donne à la fenêtre le nom de son titre : à l'ouverture, le lecteur d'écran annonce « Supprimer ce brouillon ?, boîte de dialogue ». |
id="delete-dialog-title" | h2 | La cible d'aria-labelledby. Si le texte du titre change, le nom de la fenêtre suit. |
tabindex="-1" | h2 | Permet au titre de recevoir le focus, sans le faire entrer dans l'ordre de tabulation. |
autofocus | h2 | Pose le focus sur le titre à l'ouverture : le lecteur d'écran enchaîne avec « Supprimer ce brouillon ?, titre de niveau 2 ». |
showModal() | Reste de la page | Le mode modal, lancé par command="show-modal" ou par le repli, rend la page inerte tant que la fenêtre est ouverte : ni lue, ni cliquable, ni atteignable au clavier. |
Navigation au clavier
| Touche | Action |
|---|---|
| Entrée ou Espace sur le bouton | Ouvre la fenêtre. Le focus se pose sur le titre |
| Tab et Maj+Tab | Parcourent les boutons Annuler et Supprimer. Le focus peut passer par la barre d'adresse du navigateur, jamais par la page derrière |
| Échap | Ferme la fenêtre. Le focus revient au bouton d'ouverture |
Ordre de tabulation
- Le bouton « Supprimer le brouillon », sur la page.
- Le titre de la fenêtre, à l'ouverture. Il reçoit le focus une seule fois, Tab ne revient pas dessus.
- Le bouton « Annuler ».
- Le bouton « Supprimer ». Tab repart ensuite vers « Annuler », parfois après la barre d'adresse du navigateur.
Avec un lecteur d'écran
Exemple sur Chrome avec VoiceOver. Les mots changent d'un lecteur d'écran à l'autre.
| Action | Annonce |
|---|---|
| Entrée sur le bouton | « Supprimer ce brouillon ?, boîte de dialogue », puis « Supprimer ce brouillon ?, titre de niveau 2 » |
| Tab | « Annuler, bouton » |
| Échap | « Supprimer le brouillon, bouton » |
Critères RGAA concernés
- Critère 7.1 : Chaque script est-il, si nécessaire, compatible avec les technologies d’assistance ?
- Le repli en JavaScript appelle seulement
showModal(): le rôle, le nom et l'état modal restent ceux dedialog. - Critère 10.7 : Dans chaque page web, pour chaque élément recevant le focus, la prise de focus est-elle visible ?
- Le focus reste visible sur le titre et sur les 2 boutons.
- Critère 12.8 : Dans chaque page web, l’ordre de tabulation est-il cohérent ?
- Tab ne parcourt que les boutons Annuler et Supprimer, jamais la page derrière. À la fermeture, le focus reprend au bouton d'ouverture.
- Critère 12.9 : Dans chaque page web, la navigation ne doit pas contenir de piège au clavier. Cette règle est-elle respectée ?
- Aucun piège au clavier : Échap et le bouton Annuler permettent toujours de sortir.
Autres références
WCAG 2.2
- Understanding SC 2.1.1: Keyboard (en anglais)
- Understanding SC 2.1.2: No Keyboard Trap (en anglais)
- Understanding SC 2.4.3: Focus Order (en anglais)
- Understanding SC 2.4.7: Focus Visible (en anglais)
- Understanding SC 4.1.2: Name, Role, Value (en anglais)
EN 301 549
- Accessibility requirements for ICT products and services (V4.1.1, PDF) (en anglais)Clauses 9.2.1.1, 9.2.1.2, 9.2.4.3, 9.2.4.7, 9.4.1.2
Pattern APG
- Dialog (Modal) Pattern (en anglais)
Au-delà de l'APG
| Nouveauté | Apport | Navigateurs | Dans la démo |
|---|---|---|---|
command et commandfor | Ouvrent et ferment le dialog depuis un bouton, sans script. | Chrome 135+, Firefox 144+, Safari 26.2+ | Oui |
closedby | Ferme la fenêtre par un clic sur le voile, sans script. | Chrome 134+, Firefox 141+ | Variation |
Variations
Fermeture au clic sur le voile
L'attribut closedby="any" ferme aussi la fenêtre au clic en dehors. Il n'existe pas encore dans tous les navigateurs : garde le bouton Annuler.
<dialog
id="delete-dialog"
closedby="any"
aria-labelledby="delete-dialog-title">Repli pour les anciens navigateurs
Avant décembre 2025, tous les navigateurs ne connaissaient pas command (Safari l'a ajouté en dernier, en version 26.2). Un court script prend le relais : au clic sur le bouton, dialog.showModal() ouvre la fenêtre.
La démo du haut contient déjà ce repli : essaie-la dans un navigateur d'avant décembre 2025.
<script>
// Repli : navigateurs d'avant décembre 2025, qui ne connaissent pas command
if (!('commandForElement' in HTMLButtonElement.prototype)) {
const trigger = document.querySelector('[commandfor="delete-dialog"]');
const dialog = document.getElementById('delete-dialog');
trigger.addEventListener('click', () => dialog.showModal());
}
</script>