Critères de succès WCAG · Level A
WCAG 2.1.2 : Pas de piège clavier
La norme WCAG 2.1.2 exige que les utilisateurs du clavier ne soient jamais piégés à l’intérieur d’un composant : si le focus peut être déplacé dans un élément d’interface utilisateur à l’aide du clavier, il doit également être possible de déplacer le focus en dehors en utilisant uniquement le clavier. Ce critère est essentiel pour les personnes qui s’appuient exclusivement sur la navigation au clavier, y compris les personnes ayant un handicap moteur et les utilisateurs de lecteurs d’écran.
Ce que signifie cette règle
WCAG 2.1.2 — Absence de piège au clavier — est un critère de succès de niveau A relevant du principe « Utilisable ». Il énonce : « Si le focus clavier peut être déplacé vers un composant de la page au moyen d’une interface clavier, alors le focus peut être déplacé hors de ce composant en utilisant uniquement une interface clavier et, si cela nécessite plus que des touches fléchées ou de tabulation non modifiées pour déplacer le focus, l’utilisateur est informé de la méthode permettant de déplacer le focus. »
En pratique, cela signifie que chaque composant interactif d’une page web dans lequel un utilisateur au clavier peut entrer avec la touche Tab doit également lui permettre d’en sortir avec Tab. Un piège au clavier se produit lorsqu’un utilisateur navigue dans un widget, une boîte de dialogue, un contrôle de formulaire personnalisé, un lecteur multimédia intégré ou toute autre zone focalisable, puis est incapable d’en sortir en utilisant les commandes clavier standard — il est, en pratique, coincé.
Ce critère couvre tous les éléments HTML pouvant recevoir le focus clavier : les éléments interactifs natifs tels que les balises <input>, <select>, <textarea>, <button> et <a>, ainsi que les widgets personnalisés qui reçoivent le focus via tabindex, des rôles ARIA ou une gestion du focus en JavaScript. Il s’applique également aux composants tiers intégrés tels que les widgets de chat, les lecteurs vidéo, les cartes intégrées, les sélecteurs de date et les éditeurs de texte enrichi.
Un composant respecte ce critère si un utilisateur au clavier peut toujours déplacer le focus en dehors de celui-ci en utilisant des touches standard — généralement Tab, Maj+Tab, Échap ou les flèches — ou si la page informe clairement les utilisateurs d’un mécanisme clavier non standard pour déplacer le focus. Un composant échoue si le focus se retrouve verrouillé à l’intérieur sans chemin de sortie accessible au clavier, ou si le seul mécanisme de sortie nécessite un clic de souris, un geste tactile ou une autre entrée non clavier.
Les WCAG prévoient une exception limitée : il est acceptable de contraindre temporairement le focus clavier à l’intérieur d’un composant lorsque cela fait partie d’un modèle de conception délibéré et accessible — notamment une boîte de dialogue modale. Une boîte de dialogue modale doit piéger le focus à l’intérieur de la boîte de dialogue lorsqu’elle est ouverte (pour empêcher les utilisateurs d’interagir avec le contenu d’arrière-plan masqué), mais elle doit toujours fournir un moyen accessible au clavier de fermer la boîte de dialogue et de libérer le focus — par exemple un gestionnaire de la touche Échap ou un bouton de fermeture clairement étiqueté et atteignable avec Tab. Ce type de confinement intentionnel et escapable du focus n’est pas un piège au clavier ; c’est une implémentation correcte du modèle de boîte de dialogue modale. Le piège devient un échec uniquement lorsque l’utilisateur ne peut plus s’échapper du tout.
Pourquoi c’est important
Les pièges au clavier sont parmi les défaillances d’accessibilité les plus graves qu’un site web puisse présenter. Contrairement à de nombreux autres problèmes d’accessibilité qui dégradent l’expérience de certains utilisateurs, un piège au clavier peut complètement empêcher un utilisateur de continuer à utiliser une page. C’est l’équivalent de placer une barrière physique dans un couloir sans offrir de moyen de la contourner.
Les groupes les plus gravement touchés sont les personnes ayant des handicaps moteurs ou physiques qui ne peuvent pas utiliser une souris et dépendent entièrement de la navigation au clavier. Cela inclut des personnes ayant des affections telles que les troubles musculo-squelettiques (TMS), la sclérose en plaques, la maladie de Parkinson, la tétraplégie et la paralysie cérébrale. Selon l’Organisation mondiale de la Santé, environ 1,3 milliard de personnes — soit 16 % de la population mondiale — vivent avec une forme de handicap significatif, et les déficiences motrices représentent une part substantielle de ce chiffre. Pour ces utilisateurs, rencontrer un piège au clavier sur une page de paiement, un formulaire de connexion ou un widget de chat du service client peut signifier qu’ils sont totalement incapables d’accomplir la tâche.
Les utilisateurs de lecteurs d’écran — principalement des personnes aveugles ou malvoyantes — sont également fortement impactés. Les lecteurs d’écran tels que NVDA, JAWS et VoiceOver naviguent entièrement via des commandes clavier. Si le focus se retrouve piégé dans un composant, l’utilisateur du lecteur d’écran entend le même élément se répéter à chaque pression sur Tab, sans possibilité d’avancer ou de reculer dans la page. C’est extrêmement désorientant et oblige l’utilisateur à fermer l’onglet du navigateur ou à actualiser la page, perdant ainsi toute progression réalisée.
Considérons ce scénario réel : une personne ayant une mobilité limitée des mains visite un site de e-commerce turc pour acheter un produit. Elle ajoute un article à son panier et passe à la caisse. La page de paiement inclut un widget tiers d’autocomplétion d’adresse construit avec un framework JavaScript personnalisé. Le widget ouvre une liste déroulante de suggestions lorsque le champ d’adresse reçoit le focus. Le développeur a oublié d’ajouter la gestion des événements clavier pour fermer cette liste déroulante — ainsi, une fois que l’utilisateur entre dans le champ d’adresse avec Tab et que la liste déroulante apparaît, il ne peut plus en sortir avec Tab, ne peut pas appuyer sur Échap et ne peut pas fermer la liste déroulante sans un clic de souris. L’utilisateur est complètement empêché de finaliser l’achat. Ce n’est pas un simple désagrément — c’est une exclusion totale du service.
Au-delà de l’accès pour les personnes handicapées, les pièges au clavier affectent également les utilisateurs avancés qui préfèrent la navigation au clavier pour gagner en rapidité, les utilisateurs dans des environnements d’entreprise où l’usage de la souris est restreint, et les utilisateurs de certains appareils mobiles ou hybrides dotés de claviers physiques. Corriger les pièges au clavier améliore donc l’expérience d’un public plus large que les seuls utilisateurs en situation de handicap.
Règles axe-core associées
WCAG 2.1.2 nécessite des tests manuels. Aucune règle axe-core automatisée ne détecte directement et de manière fiable les pièges au clavier. En effet, les outils automatisés fonctionnent en analysant la structure statique du DOM — ils peuvent identifier les éléments focalisables, vérifier l’ordre de tabulation et valider les attributs ARIA, mais ils ne peuvent pas simuler l’expérience complète de navigation clavier interactive qu’effectue un testeur humain. Un piège au clavier résulte généralement d’une logique de gestion des événements JavaScript qui intercepte ou supprime les événements clavier à l’exécution ; ce comportement n’est pas visible dans la structure du DOM et ne peut pas être déduit par un analyseur statique.
- Tests manuels requis — aucune règle axe-core dédiée : axe-core ne fournit pas de règle qui détecte automatiquement les pièges au clavier, car le mode de défaillance est fondamentalement comportemental. Le piège ne se manifeste que lorsqu’un utilisateur navigue réellement dans un composant avec la touche Tab et tente d’en sortir. Un analyseur automatisé ne peut pas reproduire cela, car il devrait simuler une navigation clavier séquentielle à travers chaque élément focalisable de la page, déclencher tous les écouteurs d’événements JavaScript associés, puis déterminer si le focus a bien quitté la zone prévue — un problème qui devient intractable sur le plan computationnel pour des pages complexes. De plus, ce qui constitue un piège par opposition à un confinement intentionnel du focus (comme pour une modale) nécessite un jugement contextuel que les règles automatisées ne peuvent pas rendre de manière fiable. Les testeurs doivent utiliser axe DevTools ou Lighthouse pour identifier les éléments focalisables et les problèmes d’ordre de tabulation comme point de départ, puis naviguer manuellement au clavier dans chaque zone interactive pour confirmer l’absence de pièges.
Comment tester
- Exécuter un scan d’accessibilité automatisé comme base. Ouvrez axe DevTools (extension de navigateur) ou lancez un audit d’accessibilité Lighthouse dans Chrome DevTools. Bien qu’aucun de ces outils ne signale directement un piège au clavier, le scan identifiera les éléments focalisables, les rôles ARIA manquants et les ordres de tabulation incorrects qui peuvent indiquer des composants interactifs à risque nécessitant une investigation manuelle. Notez tout widget personnalisé, iframe intégré, composant tiers, boîte de dialogue modale, menu déroulant, sélecteur de date, carrousel et éditeur de texte enrichi — ce sont les sources les plus fréquentes de pièges au clavier.
- Déconnecter ou mettre de côté votre souris. Pour que les tests clavier manuels soient valides, vous ne devez pas utiliser de souris. Placez votre souris hors de portée ou désactivez-la dans les paramètres de votre système d’exploitation pour éviter de vous y fier accidentellement pendant les tests.
- Parcourir toute la page en utilisant uniquement les touches Tab et Maj+Tab. En partant de la barre d’adresse du navigateur ou du haut de la page, appuyez de manière répétée sur Tab et observez où se déplace le focus. Suivez visuellement l’indicateur de focus à chaque étape. Lorsque vous atteignez chaque composant interactif — en particulier tout widget personnalisé, contenu intégré ou élément d’interface complexe — vérifiez qu’en appuyant sur Tab ou Maj+Tab, le focus sort proprement du composant pour aller vers l’élément focalisable suivant ou précédent de la page.
- Tester chaque composant interactif individuellement. Pour les boîtes de dialogue modales : ouvrez la modale, vérifiez que le focus se déplace à l’intérieur, puis appuyez sur Échap et confirmez que le focus revient à l’élément déclencheur. Pour les menus déroulants : ouvrez le menu, naviguez à l’intérieur, puis appuyez sur Échap et confirmez que le menu se ferme et que le focus revient au déclencheur. Pour les sélecteurs de date, sélecteurs de couleur et widgets similaires : entrez avec Tab, interagissez, puis sortez avec Tab et confirmez que le focus quitte le composant. Pour les iframes intégrées (par exemple cartes, lecteurs vidéo, widgets de chat) : entrez dans l’iframe avec Tab, naviguez à l’intérieur et confirmez que vous pouvez en sortir avec Tab pour revenir à la page principale.
- Tester avec NVDA et Firefox. Ouvrez NVDA, accédez à la page dans Firefox et utilisez Tab pour parcourir les éléments interactifs. Faites attention à ce que NVDA annonce un nouvel élément à chaque pression sur Tab ou qu’il semble revenir en boucle sur le même élément. Si Tab ne permet pas de faire avancer le focus au-delà d’un composant, il s’agit d’un piège au clavier.
- Tester avec VoiceOver et Safari sur macOS. Activez VoiceOver (Commande + F5), ouvrez la page dans Safari et utilisez la touche Tab pour naviguer. Confirmez que VoiceOver annonce un nouvel élément à chaque pression sur Tab et que le focus ne reste jamais bloqué dans une zone dont vous ne pouvez pas sortir.
- Tester avec JAWS et Chrome. Ouvrez JAWS, accédez à la page dans Chrome et utilisez Tab pour parcourir tous les composants interactifs. Testez en particulier tout composant qui utilise une gestion du focus pilotée par JavaScript, car JAWS interagit avec l’arbre d’accessibilité d’une manière qui peut révéler des pièges non visibles lors de tests visuels uniquement.
- Vérifier l’existence de mécanismes d’échappement non standard. Si un composant nécessite une touche autre que Tab, Maj+Tab ou Échap pour en sortir, vérifiez que la page communique clairement cette information à l’utilisateur — par exemple via des instructions à l’écran, une info-bulle ou une annonce via une région ARIA live lorsque le focus entre dans le composant.
Comment corriger
Boîte de dialogue modale sans gestion de la touche Échap — Incorrect
<!-- Modal opens but has no Escape key handler and no close button reachable by keyboard -->
<div id='modal' role='dialog' aria-modal='true' aria-labelledby='modal-title'>
<h2 id='modal-title'>Confirm Your Order</h2>
<p>Are you sure you want to place this order?</p>
<button onclick='submitOrder()'>Confirm</button>
<!-- No close button, no Escape key listener -- keyboard users are trapped -->
</div>
Boîte de dialogue modale sans gestion de la touche Échap — Correct
<!-- Modal with proper focus trap, Escape handler, and accessible close button -->
<div id='modal' role='dialog' aria-modal='true' aria-labelledby='modal-title'>
<h2 id='modal-title'>Confirm Your Order</h2>
<p>Are you sure you want to place this order?</p>
<button onclick='submitOrder()'>Confirm</button>
<!-- Close button is reachable by Tab and allows keyboard users to exit -->
<button id='modal-close' onclick='closeModal()' aria-label='Close dialog'>Cancel</button>
</div>
<script>
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
closeModal(); // Escape key closes the modal and returns focus to trigger
}
});
function closeModal() {
document.getElementById('modal').hidden = true;
document.getElementById('modal-trigger').focus(); // Return focus to opener
}
</script>
Menu déroulant personnalisé capturant tous les événements Tab — Incorrect
<!-- Custom dropdown intercepts all keydown events including Tab, preventing focus from leaving -->
<div id='custom-select' tabindex='0' role='combobox' aria-expanded='true'>
<ul role='listbox'>
<li role='option' tabindex='-1'>Option 1</li>
<li role='option' tabindex='-1'>Option 2</li>
<li role='option' tabindex='-1'>Option 3</li>
</ul>
</div>
<script>
// BUG: This captures ALL keyboard events and calls preventDefault on Tab,
// meaning the user can never Tab out of this component
document.getElementById('custom-select').addEventListener('keydown', function(e) {
e.preventDefault(); // This traps the keyboard
if (e.key === 'ArrowDown') { /* move focus down */ }
if (e.key === 'ArrowUp') { /* move focus up */ }
});
</script>
Menu déroulant personnalisé capturant tous les événements Tab — Correct
<!-- Correct: Only prevent default for arrow keys used for internal navigation;
allow Tab and Escape to function normally so users can exit -->
<div id='custom-select' tabindex='0' role='combobox' aria-expanded='false'>
<ul role='listbox' hidden>
<li role='option' tabindex='-1'>Option 1</li>
<li role='option' tabindex='-1'>Option 2</li>
<li role='option' tabindex='-1'>Option 3</li>
</ul>
</div>
<script>
document.getElementById('custom-select').addEventListener('keydown', function(e) {
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
e.preventDefault(); // Only prevent default for internal navigation keys
// move focus between options
}
if (e.key === 'Escape' || e.key === 'Tab') {
// Do NOT call preventDefault -- allow Tab and Escape to propagate
// so the browser can move focus away from this component naturally
closeDropdown();
}
});
</script>
Iframe tiers intégré sans chemin de sortie — Incorrect
<!-- An embedded chat widget iframe that absorbs all Tab keypresses
and never returns focus to the parent page -->
<iframe
src='https://example-chat-widget.com/embed'
title='Customer support chat'
width='350'
height='500'>
</iframe>
<!-- The iframe's internal JavaScript consumes Tab events, trapping users inside it -->
Iframe tiers intégré sans chemin de sortie — Correct
<!-- Use a button to open the chat in a new window rather than embedding
an iframe that may trap keyboard users -->
<button
id='open-chat'
onclick='window.open("https://example-chat-widget.com", "_blank", "noopener")'>
Open Customer Support Chat (opens in new window)
</button>
<!-- If an iframe must be used, add a visible skip link before it
so keyboard users can bypass it if they choose -->
<a href='#after-chat-widget' class='skip-link'>Skip chat widget</a>
<iframe
src='https://example-chat-widget.com/embed'
title='Customer support chat'
width='350'
height='500'>
</iframe>
<span id='after-chat-widget' tabindex='-1'></span>
Erreurs courantes
- Appeler
event.preventDefault()dans un écouteurkeydownsans le limiter à des touches spécifiques — appliquerpreventDefault()à tous les événements clavier sur un composant focalisable bloque le fonctionnement de Tab et Maj+Tab, créant instantanément un piège au clavier. Limitez toujourspreventDefault()uniquement aux touches spécifiques que votre composant doit gérer en interne (comme les flèches pour les listes déroulantes). - Construire une boîte de dialogue modale qui place le focus à l’intérieur mais ne fournit ni gestion de la touche Échap ni bouton de fermeture — les développeurs implémentent souvent correctement la partie « entrée du focus » du modèle de modale, mais oublient que le confinement du focus à l’intérieur d’une modale n’est acceptable que s’il existe toujours une sortie accessible au clavier. Chaque modale doit gérer la touche Échap et inclure un bouton de fermeture atteignable avec Tab.
- Utiliser
tabindex='-1'sur un élément conteneur pour l’empêcher d’apparaître dans l’ordre de tabulation, tout en permettant à JavaScript d’y déplacer le focus de manière programmatique — lorsque le focus est déplacé dans un élément avectabindex='-1'viaelement.focus(), il n’existe aucune cible naturelle pour Tab afin d’en sortir, ce qui peut bloquer l’utilisateur si aucune autre gestion clavier n’est implémentée. - Intégrer des widgets tiers (chat, cartes, vidéo) sans les auditer pour détecter un comportement de piège au clavier — les fournisseurs ne conçoivent pas toujours leurs widgets intégrés pour qu’ils soient accessibles au clavier. Les propriétaires de sites restent responsables de tout le contenu présent sur leurs pages, y compris les contenus tiers intégrés. Testez toujours manuellement les composants intégrés et, s’ils piègent les utilisateurs au clavier, entourez-les d’un lien d’évitement ou remplacez-les par une alternative sûre pour le clavier.
- Implémenter un piège de focus pour une modale ou un tiroir sans le libérer lorsque le composant se ferme — si le JavaScript qui contraint le focus n’est pas correctement nettoyé lorsque la modale se ferme, il peut continuer à intercepter les événements Tab et piéger l’utilisateur sur la couche désormais invisible.
- Utiliser les propriétés CSS
visibility: hiddenoudisplay: nonepour masquer le bouton de fermeture d’une boîte de dialogue pour des raisons de design visuel sans fournir de sortie alternative au clavier — si le bouton de fermeture est visuellement masqué mais pas retiré de l’arbre d’accessibilité, les utilisateurs de lecteurs d’écran peuvent encore le trouver ; mais s’il est également masqué de l’arbre d’accessibilité, il se peut qu’il n’y ait plus aucune sortie. Assurez-vous que tous les mécanismes de fermeture sont opérables au clavier, même s’ils sont visuellement discrets. - Construire des composants d’autocomplétion ou de saisie anticipée personnalisés qui ouvrent une liste de suggestions puis redirigent toutes les pressions sur Tab vers la navigation dans les suggestions plutôt que vers la sortie — les utilisateurs doivent pouvoir appuyer sur Échap pour fermer la liste de suggestions puis sur Tab pour passer au champ de formulaire suivant. Les widgets d’autocomplétion qui redirigent Tab vers une navigation interne enfreignent ce critère.
- Oublier de tester les éditeurs de texte enrichi (éditeurs WYSIWYG tels que TinyMCE, CKEditor ou Quill) — ces composants gèrent leurs propres interactions clavier en interne et sont une source fréquente de pièges au clavier. Confirmez toujours qu’appuyer sur Échap ou sur une séquence de touches documentée permet de quitter l’éditeur et de revenir à l’ordre de tabulation normal de la page.
- Supposer que, parce qu’un composant utilise des éléments HTML natifs, il ne peut pas créer de piège au clavier — un élément
<select>dans un formulaire qui utilise JavaScript pour surcharger son événement blur peut toujours piéger le focus. L’utilisation de HTML sémantique ne garantit pas l’absence de pièges au clavier lorsque des gestions d’événements JavaScript personnalisées sont ajoutées par-dessus. - Ne pas fournir de documentation à l’écran lorsqu’une touche non standard est requise pour sortir d’un composant — WCAG 2.1.2 autorise explicitement les composants qui nécessitent des touches non standard pour en sortir, à condition que l’utilisateur en soit informé. Si votre widget nécessite d’appuyer sur F6 ou sur une combinaison de touches personnalisée pour le quitter, vous devez le communiquer clairement à l’utilisateur, idéalement via des instructions visibles à proximité du composant ou une annonce via une région ARIA live lorsque le focus y entre.
Lien avec la réglementation d’accessibilité de la Turquie
La circulaire présidentielle 2025/10 de la Turquie, publiée au Journal officiel n° 32933 le 21 juin 2025, établit des exigences contraignantes en matière d’accessibilité numérique pour un large éventail d’entités publiques et privées opérant en Turquie. La circulaire impose la conformité à des normes d’accessibilité web reconnues au niveau international — en s’alignant sur WCAG 2.1 niveau AA comme référence de base, ce qui englobe tous les critères de niveau A, y compris WCAG 2.1.2 Absence de piège au clavier.
WCAG 2.1.2 est un critère de niveau A, qui représente le niveau minimal de conformité. En vertu de la circulaire, la conformité de niveau A est obligatoire pour toutes les entités concernées. Les institutions publiques doivent atteindre cette conformité dans l’année suivant la publication de la circulaire, tandis que les entités du secteur privé disposent de deux ans pour s’y conformer.
Les entités couvertes par la circulaire sont nombreuses et incluent les institutions publiques et organismes gouvernementaux à tous les niveaux, les plateformes de e-commerce et opérateurs de places de marché en ligne, les banques et institutions de services financiers, les hôpitaux et prestataires de soins de santé, les entreprises de télécommunications comptant 200,000 abonnés ou plus, les agences de voyage, les entreprises de transport privé et les écoles privées autorisées par le ministère de l’Éducation nationale (MoNE). Cela signifie qu’un défaut de traitement des pièges au clavier sur un site web ou une application web exploité par l’une de ces entités constitue une violation directe des obligations réglementaires d’accessibilité de la Turquie.
Étant donné la fréquence des défaillances liées aux pièges au clavier dans les applications web complexes — en particulier dans les portails de banque en ligne, les systèmes de prise de rendez-vous hospitaliers, les parcours de paiement en e-commerce et les pages de gestion de compte des opérateurs télécoms — WCAG 2.1.2 mérite une attention particulière dans le contexte de la conformité en Turquie. Ce sont précisément les types d’interfaces riches en interactions, pilotées par JavaScript, qui sont les plus susceptibles de contenir des widgets personnalisés, des boîtes de dialogue modales et des contenus tiers intégrés pouvant piéger involontairement les utilisateurs au clavier.
Les organisations soumises à la circulaire doivent considérer les tests de pièges au clavier comme une partie non négociable de leur processus d’audit d’accessibilité. Comme les outils automatisés ne peuvent pas détecter de manière fiable les pièges au clavier, les entités concernées doivent investir dans des tests clavier manuels réalisés par des spécialistes de l’accessibilité qualifiés, idéalement incluant des personnes handicapées, dans le cadre de leur démarche de conformité. Ne pas corriger les pièges au clavier identifiés lors de l’audit représente non seulement un risque juridique au regard de la circulaire, mais aussi un obstacle majeur à l’accès pour les personnes ayant des handicaps moteurs et visuels qui dépendent de la navigation au clavier pour utiliser les services numériques.
