Back

Problèmes d'accessibilité courants avec les modales (et comment les corriger)

Problèmes d'accessibilité courants avec les modales (et comment les corriger)

Les boîtes de dialogue modales sont omniprésentes dans les applications web modernes, mais elles constituent également l’une des sources les plus fréquentes de défaillances d’accessibilité. Une modale est une boîte de dialogue qui apparaît par-dessus le contenu principal et nécessite une interaction de l’utilisateur avant de pouvoir continuer. Lorsqu’elles sont mal implémentées, les modales peuvent piéger les utilisateurs naviguant au clavier, désorienter les lecteurs d’écran et créer des expériences frustrantes pour toute personne utilisant des technologies d’assistance. Examinons les problèmes d’accessibilité les plus fréquents avec les modales et leurs solutions pratiques.

Points clés à retenir

  • La gestion du focus est critique : déplacez le focus vers la modale à l’ouverture et renvoyez-le vers l’élément déclencheur à la fermeture
  • Utilisez les attributs ARIA appropriés incluant role=“dialog”, aria-modal=“true”, et des libellés accessibles
  • Implémentez une navigation clavier complète avec le cycle Tab et le support de la touche Échap
  • Rendez le contenu d’arrière-plan complètement inerte pendant que la modale est ouverte
  • Testez avec de vraies technologies d’assistance, pas seulement des outils automatisés

Le rôle critique de la gestion du focus

Le problème d’accessibilité le plus grave avec les modales est une gestion défaillante du focus. Lorsqu’une modale s’ouvre, le focus doit immédiatement se déplacer vers la modale elle-même—typiquement le premier élément interactif ou le conteneur de la modale. Lorsqu’elle se ferme, le focus doit retourner à l’élément qui l’a déclenchée.

Erreur courante : Le focus reste sur le contenu d’arrière-plan, permettant aux utilisateurs de naviguer avec Tab à travers les éléments derrière la modale.

Solution : Implémentez une gestion appropriée du focus :

// À l'ouverture de la modale
const triggerElement = document.activeElement;
modal.showModal(); // ou modal.focus() pour les implémentations personnalisées

// À la fermeture de la modale
modal.close();
triggerElement.focus();

Pour les applications React utilisant focus-trap-react :

import FocusTrap from 'focus-trap-react';

function Modal({ isOpen, onClose, children }) {
  return (
    <FocusTrap active={isOpen}>
      <div role="dialog" aria-modal="true">
        {children}
      </div>
    </FocusTrap>
  );
}

Attributs ARIA manquants ou incorrects

Les lecteurs d’écran ont besoin d’informations explicites sur les boîtes de dialogue modales pour les annoncer correctement. Des attributs ARIA manquants ou mal utilisés laissent les utilisateurs deviner l’objectif et l’état de la modale.

Erreurs courantes :

  • Absence de role="dialog" ou role="alertdialog"
  • aria-modal="true" manquant
  • Aucun nom accessible via aria-label ou aria-labelledby

Solution : Utilisez les attributs ARIA appropriés :

<!-- Utilisation de l'élément dialog natif (recommandé) -->
<dialog aria-labelledby="modal-title" aria-describedby="modal-desc">
  <h2 id="modal-title">Confirmation de suppression</h2>
  <p id="modal-desc">Cette action ne peut pas être annulée.</p>
</dialog>

<!-- Utilisation d'un div avec ARIA -->
<div role="dialog" 
     aria-modal="true" 
     aria-labelledby="modal-title"
     aria-describedby="modal-desc">
  <!-- Contenu de la modale -->
</div>

Utilisez role="alertdialog" pour les alertes critiques nécessitant une réponse immédiate de l’utilisateur, car cela déclenche des annonces plus assertives du lecteur d’écran.

Chaque modale doit être entièrement accessible au clavier. Les utilisateurs doivent pouvoir naviguer à travers les éléments interactifs avec Tab/Shift+Tab et fermer la modale avec Échap.

Erreurs courantes :

  • Aucun support de la touche Échap
  • Le focus peut s’échapper de la modale (pas de piège à focus)
  • L’ordre de tabulation ne correspond pas à la disposition visuelle

Solution : Implémentez un piège à focus complet :

function trapFocus(modalElement) {
  const focusableElements = modalElement.querySelectorAll(
    'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])'
  );
  
  const firstElement = focusableElements[0];
  const lastElement = focusableElements[focusableElements.length - 1];
  
  modalElement.addEventListener('keydown', (e) => {
    if (e.key === 'Escape') {
      closeModal();
      return;
    }
    
    if (e.key === 'Tab') {
      if (e.shiftKey && document.activeElement === firstElement) {
        e.preventDefault();
        lastElement.focus();
      } else if (!e.shiftKey && document.activeElement === lastElement) {
        e.preventDefault();
        firstElement.focus();
      }
    }
  });
  
  firstElement.focus();
}

Le contenu d’arrière-plan reste interactif

Lorsqu’une modale est ouverte, le contenu d’arrière-plan devrait être complètement inerte. Les utilisateurs ne devraient pas pouvoir interagir avec quoi que ce soit derrière la modale.

Erreur courante : L’arrière-plan reste défilable ou interactif via la navigation clavier.

Solution : Rendez le contenu d’arrière-plan inerte :

// À l'ouverture de la modale
document.body.style.overflow = 'hidden';
document.querySelector('main').setAttribute('aria-hidden', 'true');
document.querySelector('main').setAttribute('inert', ''); // Approche moderne

// À la fermeture de la modale
document.body.style.overflow = '';
document.querySelector('main').removeAttribute('aria-hidden');
document.querySelector('main').removeAttribute('inert');

Tester l’accessibilité de votre modale

Les outils automatisés détectent certains problèmes, mais les tests manuels restent essentiels :

  1. Tests au clavier :

    • Ouvrez la modale et vérifiez que le focus se déplace vers elle
    • Naviguez avec Tab à travers tous les éléments interactifs
    • Assurez-vous que Tab fait le cycle dans la modale
    • Appuyez sur Échap pour fermer
    • Vérifiez que le focus retourne à l’élément déclencheur
  2. Tests avec lecteur d’écran :

    • Testez avec NVDA (Windows) ou VoiceOver (macOS)
    • Vérifiez que le rôle de la modale est annoncé
    • Contrôlez que le titre et la description sont lus
    • Assurez-vous que le contenu d’arrière-plan n’est pas accessible
  3. Tests visuels :

    • Vérifiez que les indicateurs de focus sont visibles
    • Contrôlez le contraste des couleurs (WCAG AA exige 4,5:1 pour le texte normal, 3:1 pour le texte large et les composants d’interface)
    • Assurez-vous que les boutons de fermeture sont clairement étiquetés

Bonnes pratiques d’implémentation

Utilisez l’élément natif <dialog> quand c’est possible. Il fournit une gestion du focus intégrée et une sémantique ARIA :

const dialog = document.querySelector('dialog');
dialog.showModal(); // Ouvre avec un piège à focus approprié
dialog.close();     // Ferme et retourne le focus

Pour les implémentations personnalisées, suivez cette liste de vérification :

  • Définissez role="dialog" et aria-modal="true"
  • Fournissez un nom accessible via aria-labelledby ou aria-label
  • Implémentez un support clavier complet (Tab, Shift+Tab, Échap)
  • Créez un piège à focus robuste
  • Désactivez le défilement et l’interaction d’arrière-plan
  • Retournez le focus à l’élément déclencheur à la fermeture
  • Incluez des indicateurs de focus visibles
  • Testez avec de vraies technologies d’assistance

Conclusion

Les modales accessibles ne concernent pas seulement la conformité—elles créent de meilleures expériences pour tous les utilisateurs. En traitant ces problèmes courants, vous vous assurez que vos modales fonctionnent parfaitement pour les utilisateurs naviguant au clavier, les utilisateurs de lecteurs d’écran, et tous les autres. Commencez par du HTML sémantique, ajoutez les attributs ARIA appropriés, implémentez une gestion complète du focus, et testez toujours avec de vraies technologies d’assistance.

Rappelez-vous : si votre modale ne fonctionne pas sans souris, elle ne fonctionne pas. Corrigez ces problèmes, et vos modales seront véritablement accessibles à tous.

FAQ

Utilisez role='dialog' pour les modales standard qui contiennent des formulaires ou des informations. Utilisez role='alertdialog' pour les alertes critiques nécessitant une réponse immédiate, car cela amène les lecteurs d'écran à annoncer le contenu de manière plus assertive et interrompt la tâche actuelle de l'utilisateur.

CSS peut visuellement masquer le contenu avec des overlays et empêcher les événements de pointeur, mais cela n'arrêtera pas la navigation au clavier. Vous avez besoin de JavaScript pour ajouter aria-hidden ou l'attribut inert pour vraiment rendre le contenu d'arrière-plan non-interactif pour tous les utilisateurs.

La meilleure pratique est de focuser le premier élément interactif, typiquement le bouton de fermeture s'il est en haut. Cependant, pour les modales avec des informations critiques, focuser d'abord le titre assure que les utilisateurs de lecteurs d'écran entendent le titre avant toute action.

Truly understand users experience

See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..

OpenReplay