Aller au contenu principal

Accessibilite Angular : guide RGAA complet

Guide complet pour rendre vos applications Angular accessibles selon le RGAA : CDK a11y, FocusTrap, LiveAnnouncer, formulaires et checklist.

21 min de lectureDebutant a avance

1. Introduction : les atouts d'Angular pour l'accessibilité

Angular se distingue des autres frameworks JavaScript par une approche structurée de l'accessibilité. Contrairement à React ou Vue qui laissent largement la responsabilité au développeur, Angular embarque des outils dédiés directement dans son écosystème core.

Le premier atout est TypeScript. Le typage statique permet de détecter à la compilation des erreurs comme des propriétés ARIA mal orthographiées ou des types incompatibles. Un attribut aria-expanded qui reçoit une string au lieu d'un booléen sera signalé avant même l'exécution.

Le deuxième atout est le Component Dev Kit (CDK), et plus spécifiquement son module @angular/cdk/a11y. Ce module fournit des primitives d'accessibilité testées et maintenues par l'équipe Angular : gestion du focus, détection des interactions, annonces en live region et pièges à focus pour les modales.

Le troisième atout est Angular Material. Cette bibliothèque de composants UI implémente les patterns WAI-ARIA de référence. Les composants mat-select, mat-dialog, mat-autocomplete et mat-menu gèrent nativement les rôles ARIA, la navigation au clavier et les annonces aux lecteurs d'écran.

Enfin, le système de templates déclaratifs d'Angular avec son binding de propriétés ([attr.aria-label]) facilite la liaison dynamique des attributs d'accessibilité de manière réactive et typée. Combiné avec les pipes et la détection de changement, il offre une approche cohérente pour maintenir l'arbre d'accessibilité à jour.

2. Erreurs courantes d'accessibilité en Angular

Malgré ses atouts, Angular ne rend pas automatiquement vos applications accessibles. Voici les erreurs les plus fréquentes observées dans les projets Angular.

2.1 Composants dynamiques sans gestion du focus

L'ouverture d'une modale, d'un panneau latéral ou d'un composant chargé dynamiquement via ViewContainerRef ne déplace pas automatiquement le focus clavier. Un utilisateur de lecteur d'écran reste alors « perdu » sur l'élément déclencheur sans savoir qu'un nouveau contenu est apparu. C'est une violation directe du critère RGAA 7.1.

2.2 Formulaires template-driven sans labels

Les formulaires template-driven avec ngModel omettent souvent les éléments <label> associés, ou utilisent un placeholder comme seule indication visuelle. Sans label explicite lié par for/id ou par imbrication, les lecteurs d'écran ne peuvent pas annoncer le champ. Cela viole le critère RGAA 11.1.

2.3 routerLink sans annonce de navigation

Avec le routeur Angular, les changements de page sont des navigations SPA qui ne déclenchent pas de rechargement. Les lecteurs d'écran ne détectent pas automatiquement le changement de contexte. Sans annonce explicite ni déplacement du focus, l'utilisateur ne sait pas qu'il a changé de page, ce qui viole le critère RGAA 12.1.

2.4 ViewEncapsulation et lecteurs d'écran

Le mode ViewEncapsulation.ShadowDom utilise le Shadow DOM natif du navigateur pour isoler les styles. Or, certains lecteurs d'écran (notamment les versions anciennes de JAWS) traversent mal le Shadow DOM. Les relations ARIA cross-shadow-boundary (aria-describedby pointant vers un élément hors du shadow root) ne fonctionnent pas. Privilégiez le mode Emulated (défaut) pour une compatibilité maximale.

2.5 Utilisation abusive de *ngIf sans gestion des annonces

Les éléments affichés conditionnellement avec *ngIf (ou le nouveau @if) apparaissent et disparaissent du DOM sans aucune notification aux technologies d'assistance. Un message d'erreur, un indicateur de chargement ou une notification affichés via *ngIf doivent utiliser une live region (aria-live) ou le LiveAnnouncer du CDK pour être perceptibles.

3. Le module CDK a11y en profondeur

Le module @angular/cdk/a11y est la pièce maîtresse de l'accessibilité Angular. Il fournit quatre outils principaux que tout développeur Angular doit connaître.

3.1 FocusTrap et cdkTrapFocus

Le FocusTrap confine le focus clavier à l'intérieur d'un élément. C'est essentiel pour les modales, les panneaux latéraux et les dialogues : sans piège à focus, un utilisateur clavier peut naviguer « derrière » la modale vers des éléments invisibles. La directive cdkTrapFocus simplifie l'utilisation dans les templates.

3.2 FocusMonitor

Le FocusMonitor détecte l'origine du focus sur un élément : clavier, souris, toucher ou programmatique. Cela permet d'adapter les styles de focus selon le mode d'interaction. Un utilisateur souris n'a pas besoin du même indicateur visuel qu'un utilisateur clavier.

3.3 LiveAnnouncer

Le LiveAnnouncer permet d'annoncer du texte aux lecteurs d'écran via une live region ARIA gérée automatiquement. C'est l'outil idéal pour signaler les changements d'état, les erreurs de formulaire, les notifications et les changements de route.

3.4 InteractivityChecker

L'InteractivityChecker détermine si un élément DOM est visible, désactivé, focusable ou tabbable. Il est utilisé en interne par FocusTrap mais peut aussi servir dans vos composants pour vérifier dynamiquement l'état d'interactivité des éléments.

4. Angular Material et composants accessibles

Angular Material est construit sur le CDK et implémente les design patterns WAI-ARIA Authoring Practices. Les composants gèrent nativement les rôles, les états ARIA et la navigation clavier. Voici comment en tirer le meilleur parti pour le RGAA.

4.1 MatDialog : modale accessible

MatDialog gère automatiquement le piège à focus, le rôle dialog, aria-modal, la restauration du focus et la fermeture via Escape. Mais il faut toujours fournir un aria-label ou un aria-labelledby.

4.2 MatSelect et MatAutocomplete

Ces composants implémentent les patterns listbox et combobox WAI-ARIA. Ils gèrent les flèches directionnelles, Home/End, la recherche par frappe et les annonces d'options sélectionnées. Assurez-vous toujours de fournir un mat-label dans le mat-form-field.

4.3 MatTable : tableau de données accessible

MatTable génère un tableau HTML sémantique avec les en-têtes <th> et les cellules <td> correctement structurés. Pour le RGAA, ajoutez toujours un caption ou un aria-label au tableau, et utilisez scope sur les en-têtes si le tableau est complexe.

5. Formulaires réactifs et annonces d'erreurs

Les formulaires réactifs (ReactiveFormsModule) sont le choix recommandé pour l'accessibilité dans Angular. Ils offrent un contrôle précis sur la validation, les états et les messages d'erreur, ce qui facilite la conformité aux critères RGAA 11.1 (labels) et 11.10 (contrôle de saisie).

Points clés de cet exemple pour la conformité RGAA :

  • Labels explicites liés par for/id (critère 11.1)
  • aria-invalid sur les champs en erreur (critère 11.10)
  • aria-describedby vers les messages d'erreur (critère 11.10)
  • role="alert" sur les messages pour une annonce immédiate
  • LiveAnnouncer pour le résumé des erreurs à la soumission
  • Focus programmatique vers le premier champ en erreur
  • autocomplete pour l'aide à la saisie (critère 11.13)

6. Gestion du focus et navigation au changement de route

Dans une SPA Angular, le changement de route ne recharge pas la page. Les lecteurs d'écran ne détectent pas automatiquement le changement de contexte. Il faut implémenter trois mécanismes complémentaires : la mise à jour du titre, l'annonce de navigation et le déplacement du focus.

6.1 TitleStrategy pour le titre de page

Depuis Angular 14, la TitleStrategy permet de configurer le titre de la page automatiquement à chaque navigation. Le titre est le premier élément lu par les lecteurs d'écran et un critère RGAA obligatoire (critère 8.6).

6.2 Focus management après navigation

En complément de l'annonce du titre, déplacez le focus vers le contenu principal après chaque changement de route. Cela permet à l'utilisateur clavier de commencer à interagir immédiatement avec le nouveau contenu sans avoir à traverser toute l'en-tête.

L'attribut tabindex="-1" permet au <main> de recevoir le focus programmatiquement sans apparaître dans l'ordre de tabulation naturel. Avec Angular 17+, vous pouvez également utiliser l'événement afterNextNavigation du Router pour un timing plus précis.

7. Directives structurelles et rendu conditionnel accessible

Les directives structurelles *ngIf, *ngFor et le nouveau @if / @for d'Angular 17 manipulent le DOM. Les éléments ajoutés ou retirés ne sont pas annoncés aux technologies d'assistance par défaut. Voici comment les rendre accessibles.

7.1 Messages conditionnels avec live region

7.2 Listes dynamiques avec *ngFor

Quand une liste se met à jour dynamiquement (ajout/suppression d'éléments via *ngFor), annoncez le changement avec le LiveAnnouncer et assurez-vous que les éléments de liste restent navigables au clavier.

8. Content projection et accessibilité

Le content projection (ng-content) permet de créer des composants réutilisables qui acceptent du contenu externe. C'est un pattern puissant pour l'accessibilité car il permet de conserver la sémantique HTML du contenu projeté tout en ajoutant des comportements accessibles dans le composant hôte.

Points d'attention : le composant hôte génère un aria-labelledby dynamique lié au titre projeté. Les slots nommés (select="[card-title]") permettent de structurer le contenu projeté tout en maintenant un arbre d'accessibilité cohérent. Évitez de dupliquer des rôles ou des labels entre le composant hôte et le contenu projeté.

9. Critères RGAA clés pour Angular

Les applications Angular, comme toute SPA, sont particulièrement concernées par les critères suivants du RGAA 4.1.2. Voici les critères les plus impactés et comment les satisfaire dans un contexte Angular.

Critère 7.1 : Scripts compatibles avec les technologies d'assistance

Chaque script doit être compatible avec les technologies d'assistance ou une alternative accessible doit être proposée.

En Angular : utilisez les rôles ARIA natifs d'Angular Material, ajoutez des aria-label / aria-labelledby sur les composants interactifs custom, et testez avec NVDA et VoiceOver. Les composants générés par ViewContainerRef.createComponent() doivent recevoir les attributs ARIA nécessaires.

Critère 7.3 : Scripts utilisables au clavier et tout dispositif de pointage

Chaque script doit être contrôlable au clavier et par tout dispositif de pointage.

En Angular : chaque (click) handler doit avoir un équivalent clavier. Utilisez (keydown.enter) et (keydown.space) sur les éléments non-interactifs rendus cliquables. Le FocusMonitor du CDK aide à garantir que les styles de focus sont toujours visibles pour les utilisateurs clavier.

Critère 11.1 : Labels de champs de formulaire

Chaque champ de formulaire a-t-il une étiquette (label) ?

En Angular : avec les formulaires réactifs, associez systématiquement un <label for="id"> à chaque champ. Avec Angular Material, le <mat-label> dans un <mat-form-field> gère automatiquement l'association. Évitez les placeholders comme seule étiquette.

Critère 11.10 : Contrôle de saisie dans les formulaires

Le contrôle de saisie est-il accessible : messages d'erreur liés au champ, suggestions de correction ?

En Angular : utilisez aria-invalid pour signaler les champs en erreur, aria-describedby pour lier les messages d'erreur aux champs, et role="alert" ou LiveAnnouncer pour l'annonce immédiate. Voir la section 5 pour un exemple complet.

Critère 12.1 : Système de navigation cohérent

Chaque ensemble de pages dispose-t-il de deux systèmes de navigation au moins ?

En Angular : implémentez un lien d'évitement (<a href="#main-content">Aller au contenu principal</a>), une navigation principale cohérente et un plan du site ou un moteur de recherche. Avec le routeur Angular, assurez-vous que l'état actif de la navigation (routerLinkActive) est aussi communiqué via aria-current="page".

10. Packages et outils recommandés

Voici les packages et outils essentiels pour construire et maintenir des applications Angular accessibles.

@angular/cdk/a11y

Module officiel du CDK Angular. Fournit FocusTrap, FocusMonitor, LiveAnnouncer, InteractivityChecker et ListKeyManager. C'est la base de toute stratégie d'accessibilité Angular.

angular-eslint (successeur de codelyzer)

Règles ESLint spécifiques à Angular incluant des règles d'accessibilité : détection des labels manquants, des attributs ARIA invalides, des éléments interactifs sans rôle clavier. Remplace l'ancien codelyzer depuis Angular 13+.

pa11y-ci

Outil de test d'accessibilité automatisé en CI/CD. Teste vos pages Angular contre les WCAG 2.1 AA. Configurez-le avec les URLs de votre application pour des tests à chaque pull request.

axe-core / @axe-core/webdriverjs

Moteur de tests d'accessibilité de Deque. Intégrez-le dans vos tests e2e Cypress ou Playwright pour détecter automatiquement les violations d'accessibilité. Compatible avec les composants Angular rendus côté client.

ngx-accessibility

Bibliothèque communautaire Angular fournissant des directives d'accessibilité supplémentaires : gestion du focus au changement de route, annonces automatiques, détection de l'orientation du media query. Complément utile au CDK pour des besoins spécifiques.

Lighthouse CI

L'audit d'accessibilité de Lighthouse peut être automatisé dans votre pipeline CI. Définissez un seuil minimum de score d'accessibilité (par exemple 90/100) et échouez le build si le seuil n'est pas atteint.

11. Checklist accessibilité Angular

Utilisez cette checklist pour vérifier l'accessibilité de vos composants et pages Angular avant chaque mise en production.

Structure et sémantique

  • Hiérarchie des titres cohérente (h1 unique par page, h2, h3 sans saut)
  • Lien d'évitement vers le contenu principal fonctionnel
  • Landmarks ARIA ou éléments HTML5 sémantiques (main, nav, aside, footer)
  • Langue de la page déclarée (lang sur <html>)
  • Titre de page unique et descriptif (TitleStrategy)

Composants interactifs

  • Tous les composants interactifs sont accessibles au clavier (Tab, Enter, Space, Escape)
  • Indicateur de focus visible sur tous les éléments focusables
  • Modales et dialogues utilisent cdkTrapFocus ou MatDialog
  • Rôles ARIA corrects sur les composants custom (tabs, accordion, menu, tooltip)
  • Pas d'éléments <div> ou <span> avec (click) sans rôle ni tabindex

Formulaires

  • Chaque champ possède un label explicite (critère RGAA 11.1)
  • Messages d'erreur liés aux champs via aria-describedby
  • aria-invalid="true" sur les champs en erreur
  • Erreurs annoncées via LiveAnnouncer ou role="alert"
  • Attribut autocomplete sur les champs d'identité et de paiement
  • Focus déplacé vers le premier champ en erreur à la soumission

Navigation SPA

  • Titre de page mis à jour à chaque changement de route
  • Annonce de navigation aux lecteurs d'écran (LiveAnnouncer)
  • Focus déplacé vers le contenu principal après navigation
  • État actif de la navigation communiqué (aria-current="page")
  • Indicateurs de chargement annoncés (aria-busy, role="status")

Contenu dynamique

  • Live regions pour les notifications et mises à jour (aria-live)
  • Conteneur aria-live présent dans le DOM avant l'apparition du contenu
  • Résultats de recherche annoncés (nombre de résultats)
  • ViewEncapsulation.Emulated (défaut) utilisé au lieu de ShadowDom

Tests

  • angular-eslint avec règles d'accessibilité activées
  • Tests axe-core dans la suite e2e (Cypress, Playwright)
  • Test manuel de navigation au clavier (Tab, Shift+Tab, Enter, Space, Escape, Flèches)
  • Test avec un lecteur d'écran (VoiceOver sur macOS, NVDA sur Windows)
  • Vérification du zoom à 200% sans perte de contenu
  • Score Lighthouse Accessibility >= 90

Questions fréquentes

Angular est-il accessible par defaut ?

Angular fournit des outils solides comme CDK a11y et Angular Material, mais l'accessibilite depend toujours de votre implementation.

Quelle est la difference entre FocusTrap et cdkTrapFocus ?

FocusTrap est l'API programmatique du CDK a11y, tandis que cdkTrapFocus est sa directive Angular prete a l'emploi dans les templates.

Comment annoncer les changements de route aux lecteurs d'ecran dans Angular ?

Utilisez TitleStrategy, LiveAnnouncer et un deplacement du focus vers le contenu principal apres chaque NavigationEnd.

Angular Material est-il conforme RGAA ?

Angular Material aide beaucoup, mais il ne garantit pas la conformite RGAA sans labels explicites, tests et verifications manuelles.

Comment tester l'accessibilite d'une application Angular ?

Combinez angular-eslint, axe-core dans vos tests e2e, navigation clavier, zoom et lecteur d'ecran dans votre recette.

ViewEncapsulation affecte-t-il l'accessibilite ?

Oui. Le mode ShadowDom peut compliquer la lecture et les references ARIA. Emulated reste le meilleur choix generaliste.

Quels criteres RGAA sont les plus impactes par Angular ?

Les plus critiques touchent les scripts, le clavier, les formulaires, les messages d'erreur et la navigation dans les interfaces dynamiques.

Verifiez l'accessibilite de votre application Angular

RGAA Scanner analyse automatiquement votre site Angular contre les criteres du RGAA et genere un rapport detaille avec des recommandations de correction.

Scanner mon application Angular