Communitygithub.com

accessibilite-frontend

Applique WCAG 2.1 AA — HTML sémantique d'abord, ARIA uniquement là où le HTML ne suffit pas, navigation clavier complète, focus visible, contrastes, formulaires étiquetés et respect des préférences de mouvement. Se déclenche pour l'ajout d'une modale, la construction d'un menu déroulant, la validation de formulaire, la navigation clavier, le lecteur d'écran, le contraste et l'audit d'accessibilité.

Qu'est-ce que accessibilite-frontend ?

Cette compétence garantit la conformité WCAG 2.1 AA pour tous les composants interactifs et les pages front-end d'un projet. Elle impose l'utilisation prioritaire du HTML sémantique (boutons, liens, labels, landmarks) avant le recours aux attributs ARIA, et exige une navigation clavier complète avec un focus visible. La compétence traite du contraste des couleurs (4.5:1 pour le texte normal), des images avec texte alternatif, de la gestion des formulaires avec erreurs liées via `aria-describedby`, de la taille des cibles (44×44 CSS px comme minimum sur les surfaces tactiles) et du respect de la préférence de mouvement réduite. Elle inclut également une checklist de test couvrant le clavier, le lecteur d'écran, les couleurs, l'animation et un scan automatisé avec Axe via Playwright. Les conventions du projet sont résolues via STACK-PROFILE.md.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/chandra-pangea/plugin-ax-ai-ts-full-stack/tree/HEAD/claude/skills/frontend-accessibility

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Accessibilité du Frontend

S'applique aux composants dans <ui-packages-dir> et aux pages dans <web-dir>/src/. L'objectif est le niveau WCAG 2.1 AA, et il s'agit d'un plancher, pas d'un objectif.

Résolution des conventions du projet

Les valeurs entre chevrons proviennent du profil de la pile du projet. Résolvez-les dans cet ordre :

  1. Lisez STACK-PROFILE.md à la racine du dépôt et utilisez ses valeurs textuellement.
  2. S'il est absent ou qu'une clé manque, déduisez-les du dépôt — css-strategy et ui-framework à partir des dépendances de l'application web.
  3. Si toujours non résolu, conformez-vous à la convention dominante déjà présente dans le dépôt.
  4. Uniquement lorsque le dépôt est vide, revenez à la valeur par défaut indiquée dans cette compétence — puis écrivez les valeurs choisies dans STACK-PROFILE.md.

N'inventez jamais une nouvelle convention quand le dépôt en exprime déjà une.


Règles strictes

1. HTML sémantique d'abord

  • <button> pour les actions, <a> pour la navigation. Jamais de <div> avec un gestionnaire de clic.
  • Les niveaux de titres descendent sans saut.
  • <label> pour chaque champ de formulaire, associé avec htmlFor.
  • <fieldset> et <legend> pour les contrôles groupés.
  • Les points de repère — <nav>, <main>, <footer>, <aside> — sur chaque page.

2. ARIA uniquement là où HTML ne peut pas

L'ordre de préférence est l'élément sémantique, puis l'attribut ARIA, puis le comportement personnalisé. N'utilisez jamais ARIA pour remplacer la sémantique qu'un élément porte déjà — un role="button" sur une <div> réimplémente, mal, ce que <button> offre gratuitement.

Un ARIA incorrect est pire que pas d'ARIA : un aria-label erroné remplace silencieusement le nom accessible qu'un lecteur d'écran aurait autrement calculé correctement.

3. Le fonctionnement au clavier est obligatoire

  • Tout élément interactif est accessible via Tab.
  • L'ordre de tabulation suit l'ordre visuel.
  • Le focus est toujours visible. Ne supprimez jamais un contour sans le remplacer.
  • Échap ferme les dialogues et popovers ; Entrée et Espace activent les contrôles ; les touches fléchées se déplacent dans les widgets composites.
  • Les widgets personnalisés gèrent le focus explicitement.

4. Couleur et contraste

  • 4.5:1 pour le texte normal, 3:1 pour le texte grand (18 px, ou 14 px en gras) et pour les limites d'interface significatives.
  • La couleur ne véhicule jamais de sens seule — associez-la à du texte, une icône ou un motif.
  • Les deux thèmes sont vérifiés, pas seulement celui par défaut.

5. Images et médias

  • Chaque image a un alt. Descriptif pour le contenu, alt="" pour la décoration.
  • Jamais « image », « photo » ou le nom du fichier.
  • Les images complexes reçoivent une description longue via aria-describedby ou une légende.
  • La vidéo comporte des sous-titres ; l'audio comporte une transcription.

6. Formulaires

  • Chaque champ est étiqueté.
  • Les erreurs sont liées avec aria-describedby et annoncées avec role="alert".
  • Les champs invalides sont marqués aria-invalid.
  • Les champs obligatoires sont marqués avec l'attribut required — et si un astérisque est affiché, sa signification est précisée textuellement quelque part.
  • Lors d'un échec de soumission, le focus se déplace vers le premier champ invalide.

7. Taille des cibles

WCAG 2.1 AA n'a pas de taille de cible minimale (2.2 AA fixe 24×24 px CSS ; le chiffre de 44×44 est 2.1 AAA et la convention HIG de la plateforme). Considérez 44×44 comme le plancher pour les actions principales sur les surfaces tactiles, et appliquez-le comme suit :

  • Actions principales et destructrices, et tout ce qu'un utilisateur atteint sur un téléphone : 44×44.
  • Chrome de bureau dense — barres d'outils, actions de lignes de tableau, contrôles de formulaire compacts — peut être plus petit, jusqu'à 24×24, à condition que les cibles ne soient pas adjacentes à d'autres cibles et qu'un contrôle de taille équivalente existe ailleurs.
  • L'espacement compte. Un contrôle de 32 px avec 6 px d'espace libre de chaque côté répond au critère 2.2 ; un contrôle de 32 px collé à son voisin, non.

Les bibliothèques de composants vendues sont généralement en dessous de ce plancher — une hauteur de bouton par défaut de 32 ou 36 px CSS est courante. Ne modifiez pas manuellement le fichier vendu pour le corriger, et ne considérez pas le décalage comme acceptable par défaut. Augmentez la valeur par défaut dans <wrappers-pkg> pour que chaque consommateur hérite de la taille conforme, et conservez les tailles plus petites comme options explicites pour les contextes denses. Ainsi, le choix accessible est celui que vous obtenez sans y penser.

Enregistrez la résolution choisie par le projet dans STACK-PROFILE.md. Une dérogation non documentée est redécouverte comme un bug tous les six mois.

8. Mouvement

  • Respectez prefers-reduced-motion.
  • Le contenu à lecture automatique dispose d'un contrôle de pause.
  • Rien ne clignote plus de trois fois par seconde.

9. Les tests font partie du travail

  • Utilisez la fonctionnalité uniquement avec le clavier.
  • Écoutez-la avec un lecteur d'écran — VoiceOver sur macOS, NVDA sur Windows.
  • Exécutez une analyse automatisée dans la suite de tests de bout en bout.

Les outils automatisés détectent environ un tiers des vrais problèmes. Ils sont un plancher, pas un laissez-passer.


Modèles

Les implémentations complètes se trouvent dans references/component-patterns.md. Ce que chaque modèle garantit :

  • Bouton — un <button> sémantique dont l'anneau de focus apparaît pour les utilisateurs clavier mais pas pour les clics de souris (focus-visible), avec des transitions respectueuses du mouvement et une propriété ariaLabel pour une utilisation avec icône uniquement.
  • Champ de formulaire — un champ étiqueté dont le texte d'erreur est lié par programme avec aria-describedby, annoncé avec role="alert" et signalé avec aria-invalid ; l'astérisque obligatoire est aria-hidden.
  • Dialogue — un <dialog> natif utilisant showModal() pour le piégeage gratuit du focus, la gestion de Échap et l'arrière-plan inerte ; le focus se déplace à l'ouverture et revient au déclencheur à la fermeture.
  • Liste déroulante — une sélection personnalisée avec navigation par touches fléchées et câblage ARIA correct (aria-activedescendant, role="listbox") ; construisez-la uniquement lorsqu'un <select> natif ne convient pas.
  • Lien d'évitement — permet aux utilisateurs clavier de sauter la navigation, visible uniquement lorsqu'il est ciblé ; la cible porte tabIndex={-1} pour que le focus s'y pose réellement.

Référence rapide WCAG

PrincipeExigenceEn pratique
PerceptibleContenu disponible pour tous les sensTexte alternatif, sous-titres, couleur plus icône
UtilisableTout est accessible au clavierOrdre de tabulation, Échap ferme, focus visible
CompréhensiblePrévisible, clairement formuléNavigation cohérente, langage simple
RobusteFonctionne avec les technologies d'assistanceHTML valide, ARIA correct, éléments sémantiques
ProblèmeCorrectif
Champ non étiquetéAjouter <label htmlFor>
Faible contrasteAtteindre 4.5:1, ou 3:1 pour le texte grand
Aucun chemin clavierÉléments interactifs réels, focus géré
Alt manquantDécrire, ou alt="" si décoratif
Sens uniquement par la couleurAjouter du texte ou une icône
Bouton avec icône uniquementAjouter aria-label
Contenu clignotantRester sous trois clignotements par seconde

Préférences de mouvement

Gérez le mouvement réduit en CSS pur. Une variante de classe utilitaire telle que motion-safe: ne s'applique que lorsque le mouvement est autorisé, donc la placer dans une requête de mouvement réduit produit une règle qui ne peut jamais correspondre.

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

Une valeur proche de zéro plutôt que none permet aux événements de fin de transition de se déclencher, afin que les composants qui les attendent ne bloquent pas.

Pour un contrôle par composant, appliquez la variante motion-safe: à l'utilitaire animé lui-même — motion-safe:transition-colors, comme dans le Bouton ci-dessus.

Contenu visuellement masqué

La plupart des frameworks utilitaires fournissent déjà sr-only et not-sr-only. Utilisez-les ; ne les redéfinissez pas. Si le vôtre ne le fait pas, l'implémentation de référence se trouve dans references/component-patterns.md.


Liste de vérification des tests

Clavier

  • Chaque élément interactif accessible via Tab
  • L'ordre de tabulation correspond à l'ordre visuel
  • Le focus est toujours visible
  • Échap ferme les dialogues et popovers
  • Les touches fléchées fonctionnent dans les widgets composites
  • Le focus revient au déclencheur lorsqu'un dialogue se ferme

Lecteur d'écran

  • Tout le contenu est accessible
  • Les fonctions des contrôles sont claires sans contexte environnant
  • Les labels sont annoncés avec leurs champs
  • Les erreurs sont annoncées via role="alert"
  • Les points de repère sont présents
  • Les éléments décoratifs sont masqués avec aria-hidden

Couleur

  • 4.5:1 pour le texte normal, 3:1 pour le texte grand et les limites d'interface
  • Pas de sens uniquement par la couleur
  • Les deux thèmes vérifiés

Mouvement

  • Mouvement réduit respecté
  • Pas de clignotement au-delà de trois par seconde
  • Contenu à lecture automatique pouvant être mis en pause

Automatisé

Les analyses sont exécutées dans la suite Playwright — voir frontend-testing. L'extrait Axe-in-Playwright se trouve dans references/component-patterns.md.

Documents de référence

Analyse approfondieRéférence
Implémentations de composants accessibles : bouton, champ de formulaire, modale, liste déroulante, lien d'évitementreferences/component-patterns.md

Compétences connexes

  • frontend-architecture — couches de composants et thématisation
  • frontend-testing — où ces vérifications sont exécutées
  • frontend-component-docs — documentation du contrat d'accessibilité d'un composant

Skills associés