Skip to Content

Chapitre 13.2 — Gestes & pointeur

⏱️ TL;DR — Un geste complexe (swipe, pincement, tracé, appui à deux doigts) ne doit jamais être le seul moyen d’accéder à une fonction. Le critère 2.5.1 exige une alternative à pointeur unique (un simple tap suffit) ; le 2.5.2 demande l’annulation du pointeur — déclencher l’action au relâchement, pas à l’appui, pour qu’on puisse se rétracter ; et le 2.5.7 (WCAG 2.2) impose une alternative au glisser-déposer (ex. des boutons monter/descendre). Toute personne qui pilote au clavier, au contacteur ou à la voix — ou qui a du mal à tracer un geste — dépend de ces alternatives.

🎯 Objectifs

  • Distinguer geste simple (tap) et geste complexe (swipe, pincement, tracé, multipoint).
  • Fournir une alternative à pointeur unique à tout geste complexe (2.5.1).
  • Appliquer l’annulation du pointeur : agir au relâchement (2.5.2).
  • Offrir une alternative au glisser-déposer (2.5.7).

Geste simple vs geste complexe

Un geste à pointeur unique simple, c’est un tap (ou un clic) à un endroit. Tout le monde peut le faire, y compris via un lecteur d’écran, un contacteur ou la commande vocale, qui savent « activer l’élément X ».

Un geste complexe, c’est :

  • un tracé dépendant du chemin (path-based) : swipe, glissé, dessin d’une forme ;
  • un geste multipoint : pincement pour zoomer, rotation à deux doigts, appui à trois doigts.

Le problème : une commande vocale ne sait pas « pincer », un contacteur ne sait pas « tracer une diagonale », et une personne avec des tremblements rate le geste. D’où la règle.

2.5.1 — Toujours une alternative à pointeur unique

Le critère 2.5.1 Gestes du pointeur (A, WCAG 2.1) : si une fonction s’utilise avec un geste complexe, elle doit aussi s’utiliser avec un geste simple (un tap), sauf si le geste complexe est essentiel (rare : une signature manuscrite, par exemple).

<!-- ❌ Le carrousel n'avance QU'au swipe : injouable au clavier, à la voix, au contacteur --> <div class="carousel" ontouchmove="onSwipe(event)"> <!-- slides… --> </div>
<!-- ✅ Le swipe reste possible, MAIS des boutons offrent l'alternative simple --> <div class="carousel"> <!-- slides… --> <button type="button" onclick="prev()" aria-label="Diapositive précédente">‹</button> <button type="button" onclick="next()" aria-label="Diapositive suivante">›</button> </div>

Le swipe reste un bonus pour ceux qui l’aiment ; il n’est jamais le seul chemin.

⚠️ Piège — Réserver une action uniquement à un geste. Le classique : supprimer un e-mail seulement en swipant la ligne vers la gauche, sans bouton « Supprimer » visible ou accessible. Résultat : la fonction n’existe pas pour qui n’atteint pas le swipe. Chaque action déclenchée par un geste doit avoir un bouton ou une commande équivalents.

2.5.2 — Annulation du pointeur

Le critère 2.5.2 Annulation du pointeur (A, WCAG 2.1) protège contre les activations accidentelles. La règle : déclenche l’action au relâchement (up), pas au moment où le doigt touche (down). Ainsi, si l’utilisateur pose le doigt sur le mauvais bouton, il peut glisser hors de la cible avant de relâcher pour annuler.

// ❌ Action au premier contact : impossible d'annuler une erreur de visée button.addEventListener('pointerdown', () => envoyer());
// ✅ Action au relâchement : glisser hors du bouton avant de lever = annulation button.addEventListener('pointerup', () => envoyer());

Bonne nouvelle : un <button> HTML natif fait déjà ça. Le click se déclenche au relâchement sur l’élément, et sortir avant de relâcher l’annule. C’est encore un argument pour utiliser les éléments natifs plutôt que des gestionnaires pointerdown maison.

Côté utilisateur — Pour quelqu’un qui vise mal (tremblements, écran tenu en marchant), l’annulation au relâchement est un filet de sécurité : « oups, mauvais bouton » se corrige en glissant le doigt ailleurs avant de lever, sans conséquence. Déclencher au down supprime ce filet et transforme la moindre imprécision en erreur irréversible.

2.5.7 — Alternative au glisser-déposer

Le critère 2.5.7 Mouvements de glissement (AA, WCAG 2.2) vise le drag-and-drop : réordonner une liste, déplacer une carte de kanban, ajuster un curseur en glissant. Ces gestes demandent de maintenir et déplacer avec précision — difficile au contacteur, à la voix, ou avec une motricité fine réduite.

La règle : toute fonctionnalité de glisser doit avoir une alternative sans glisser (un simple pointeur unique).

<!-- ✅ Réordonner une liste : le drag existe, MAIS chaque item a monter/descendre --> <li> Module « Introduction » <button type="button" onclick="monter(id)" aria-label="Monter ce module">▲</button> <button type="button" onclick="descendre(id)" aria-label="Descendre ce module">▼</button> </li>

Pour un curseur (slider) qu’on glisse, l’alternative native existe déjà : un <input type="range"> se règle aussi aux flèches du clavier. Encore une raison de préférer le composant natif.

🧭 Sur A11yLearn — Dans l’éditeur de parcours d’A11yLearn, le formateur réordonne les modules par glisser-déposer. On a d’abord livré seulement le drag : injouable au clavier et au contacteur. Correctif : chaque module a désormais des boutons « Monter » / « Descendre » (alternative 2.5.7) et un menu « Déplacer vers la position… ». Le drag reste là pour la souris ; il n’est plus le seul moyen.

📚 Aller plus loin — Critères 2.5.1 Pointer Gestures, 2.5.2 Pointer Cancellation (A, WCAG 2.1) et 2.5.7 Dragging Movements (AA, WCAG 2.2) sur w3.org/WAI. Règle de conception : un geste peut enrichir l’expérience, jamais la verrouiller.

✏️ Exercices

Exercice 1 — Le swipe exclusif. Une messagerie n’offre « Archiver » et « Supprimer » qu’en swipant la ligne. Quel critère est en cause, et comment corriger ?

✅ Solution

C’est le critère 2.5.1 (alternative à pointeur unique) : le swipe est un geste basé sur le tracé, et il est ici le seul moyen d’archiver ou supprimer. Correctif : ajouter des boutons « Archiver » et « Supprimer » accessibles (un menu d’actions par ligne, ou des boutons visibles), qui font la même chose d’un simple tap. Le swipe peut rester en raccourci.

Exercice 2 — down ou up ? Un développeur déclenche l’envoi d’un formulaire sur pointerdown « pour que ça réponde plus vite ». Pourquoi est-ce un problème d’accessibilité ?

✅ Solution

Ça viole le critère 2.5.2 (annulation du pointeur). En agissant au contact (down), on retire à l’utilisateur la possibilité d’annuler en glissant hors de la cible avant de relâcher. Une erreur de visée devient irréversible. Il faut agir au relâchement (up/click) — ce que fait déjà un <button> natif.

🧠 Quiz de révision

1. Qu’exige le critère 2.5.1 pour un carrousel piloté au swipe ?

Une alternative à pointeur unique simple : des boutons « précédent / suivant » activables d’un tap. Le swipe (geste basé sur le tracé) ne peut pas être le seul moyen d’avancer, sauf s’il est essentiel — ce qui n’est pas le cas d’un carrousel.

2. Que signifie « annulation du pointeur » (2.5.2) ?

Déclencher l’action au relâchement du doigt (up), pas au contact (down), pour qu’on puisse glisser hors de la cible avant de lever et ainsi annuler une activation accidentelle. Les <button> natifs le font déjà.

3. Que demande le critère 2.5.7, et pour qui ?

Une alternative au glisser-déposer : toute fonction de drag (réordonner, déplacer) doit être faisable sans glisser, via un simple pointeur unique. C’est vital pour les utilisateurs de contacteur, de commande vocale, ou à motricité fine réduite.

4. Donne une alternative concrète au drag pour réordonner une liste.

Des boutons « Monter » / « Descendre » sur chaque élément, et/ou un menu « Déplacer vers la position… ». Chacun réordonne d’un simple tap, sans maintenir ni glisser.

5. Pourquoi préférer un composant natif pour un curseur (slider) ?

Parce qu’un <input type="range"> gère nativement le réglage aux flèches du clavier — une alternative au glissement (2.5.7) offerte gratuitement — et l’activation au relâchement. Refaire un slider en <div> oblige à recoder toutes ces alternatives à la main.


Chapitre suivant : Orientation & zoom — laisser tourner l’écran en portrait et paysage, et ne jamais désactiver le zoom du navigateur.

Last updated on