Aller au contenu
Me contacter

Toutes les briques

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

Supprimer ce brouillon ?

Le brouillon sera supprimé définitivement.

Anatomie

  1. button command="show-modal" Le bouton d'ouverture, relié à la fenêtre par commandfor.
  2. dialog La fenêtre, placée au-dessus de toute la page.
  3. h2 autofocus Le titre, qui nomme la fenêtre et reçoit le focus à l'ouverture.
  4. Contenu La phrase qui dit ce que la suppression entraîne.
  5. form method="dialog" Les boutons Annuler et Supprimer, qui ferment la fenêtre sans script. La value du bouton choisi passe dans returnValue.
  6. ::backdrop Le voile posé sur la page.

Code HTML

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>
CSS
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 de dialog : 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émentDescription
commandfor="delete-dialog"buttonDé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"buttonOuvre la fenêtre en mode modal, sans script. À la fermeture, le focus revient sur ce bouton.
Rôle dialog (implicite)dialogLe lecteur d'écran reçoit une boîte de dialogue, modale puisque show-modal l'a ouverte.
aria-labelledby="delete-dialog-title"dialogDonne à 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"h2La cible d'aria-labelledby. Si le texte du titre change, le nom de la fenêtre suit.
tabindex="-1"h2Permet au titre de recevoir le focus, sans le faire entrer dans l'ordre de tabulation.
autofocush2Pose 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 pageLe 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

ToucheAction
Entrée ou Espace sur le boutonOuvre la fenêtre. Le focus se pose sur le titre
Tab et Maj+TabParcourent les boutons Annuler et Supprimer. Le focus peut passer par la barre d'adresse du navigateur, jamais par la page derrière
ÉchapFerme la fenêtre. Le focus revient au bouton d'ouverture

Ordre de tabulation

  1. Le bouton « Supprimer le brouillon », sur la page.
  2. Le titre de la fenêtre, à l'ouverture. Il reçoit le focus une seule fois, Tab ne revient pas dessus.
  3. Le bouton « Annuler ».
  4. 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.

ActionAnnonce
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 de dialog.
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

Au-delà de l'APG

NouveautéApportNavigateursDans la démo
command et commandforOuvrent et ferment le dialog depuis un bouton, sans script.Chrome 135+, Firefox 144+, Safari 26.2+Oui
closedbyFerme 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.

Supprimer ce brouillon ?

Le brouillon sera supprimé définitivement.

Un clic sur le voile ferme aussi la fenêtre.

Code
<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.

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