Guides Vue.js

Accessibilité avec Vue.js : composants a11y, directives et bonnes pratiques RGAA

Vue.js et l'accessibilité : un framework bien équipé

Vue.js est le deuxième framework JavaScript le plus populaire en France, particulièrement apprécié dans l'écosystème Nuxt.js. Sa syntaxe de templates proche du HTML et son système réactif facilitent la création d'interfaces accessibles — à condition de connaître les bonnes pratiques.

ARIA dans les templates Vue

Binding dynamique des attributs ARIA

Vue permet de lier dynamiquement les attributs ARIA avec v-bind (ou son raccourci :) :

<button :aria-expanded="isMenuOpen" :aria-controls="'menu-' + menuId" @click="toggleMenu">{{ menuLabel }}</button>

Les attributs ARIA réactifs sont un avantage majeur de Vue : ils se mettent à jour automatiquement avec l'état du composant.

Attributs ARIA courants en Vue

  • :aria-label="labelText" : label dynamique pour les lecteurs d'écran
  • :aria-hidden="!isVisible" : masquer/afficher aux technologies d'assistance
  • :aria-live="importance" : annonces de changements dynamiques
  • :aria-invalid="hasError" : état de validité des champs de formulaire
  • :aria-selected="isSelected" : état de sélection dans les listes

Composants accessibles en Vue

Structure d'un composant accessible

Chaque composant Vue doit respecter ces principes :

  • Utiliser des éléments HTML sémantiques dans le template
  • Exposer les props nécessaires pour les labels et descriptions (label, description, errorMessage)
  • Gérer les événements clavier (Escape, Enter, flèches) via @keydown
  • Émettre des événements pour communiquer les changements d'état au composant parent
  • Utiliser des refs pour la gestion du focus (this.$refs.input.focus())

Exemple : composant Dialog accessible

Un dialogue modal en Vue doit :

  • Se téléporter dans le body avec <Teleport to="body"> (Vue 3)
  • Piéger le focus à l'intérieur (premier élément focusable → dernier → boucle)
  • Se fermer avec Escape
  • Retourner le focus à l'élément déclencheur à la fermeture
  • Avoir un role="dialog" et un aria-labelledby pointant vers le titre
  • Masquer le reste de la page avec aria-hidden="true" sur l'élément racine

Vue Router et accessibilité

Les SPA Vue avec Vue Router posent des défis de navigation :

  • Annonce de page : utilisez un composant global qui annonce le titre de la page via une live region à chaque changement de route
  • Gestion du focus : dans le hook afterEach du routeur, déplacez le focus vers le <h1> ou le <main>
  • Titre de page : mettez à jour document.title à chaque navigation via le meta du routeur
  • Skip links : ajoutez un lien « Aller au contenu principal » en haut de chaque page

Directives personnalisées pour l'accessibilité

v-focus : focus automatique

Créez une directive pour gérer le focus automatique :

app.directive('focus', { mounted(el) { el.focus(); } });

Utilisation : <input v-focus />

v-announce : annonce aux lecteurs d'écran

Une directive pour annoncer des messages via une live region globale, utile pour les notifications, validations et changements d'état dynamiques.

Bibliothèques et écosystème

  • Headless UI Vue : composants sans style (Dialog, Menu, Listbox, Switch, Tabs) avec accessibilité intégrée
  • Radix Vue : portage des primitives Radix pour Vue, excellente accessibilité
  • PrimeVue : bibliothèque complète avec un bon niveau d'accessibilité (WCAG 2.1 AA)
  • Vuetify : Material Design pour Vue avec support ARIA, mais vérifiez les composants complexes
  • vue-axe : intégration d'axe-core dans le workflow de développement Vue

Nuxt.js et accessibilité

Nuxt.js, le meta-framework Vue, apporte des avantages pour l'accessibilité :

  • SSR (Server-Side Rendering) : le contenu est disponible même sans JavaScript, améliorant la compatibilité avec les technologies d'assistance anciennes
  • useHead() : gestion du titre de page et des meta via le composable
  • NuxtLink : le composant de navigation gère les transitions de manière fluide
  • Layouts : les layouts Nuxt permettent de centraliser les landmarks (header, main, footer, nav)

Tests d'accessibilité en Vue

  • @vue/test-utils + jest-axe : tests automatisés de conformité
  • Cypress + cypress-axe : tests end-to-end avec vérification d'accessibilité
  • vue-axe : analyse en temps réel pendant le développement (overlay dans le navigateur)
  • ESLint plugin vue-a11y : détection au développement des erreurs courantes
Vue.js, combiné avec les bonnes bibliothèques et pratiques, permet de créer des applications pleinement accessibles. La réactivité de Vue facilite la mise à jour des attributs ARIA en temps réel.
Les deux frameworks sont équivalents en termes de capacité d'accessibilité. La syntaxe de templates Vue est plus proche du HTML natif, ce qui peut réduire les erreurs. Mais l'écosystème React (React Aria, eslint-plugin-jsx-a11y) est plus mature. Le choix dépend de vos préférences et de votre équipe.
Créez un composant global contenant une div avec aria-live="assertive" qui affiche le titre de la page. Dans le afterEach du routeur, mettez à jour ce titre et déplacez le focus vers le h1 de la nouvelle page. Le plugin vue-announcer automatise ce processus.
Headless UI Vue (Tailwind Labs) et Radix Vue offrent les composants les plus accessibles sans imposer de style. PrimeVue est une bonne option si vous cherchez des composants stylés avec un bon niveau d'accessibilité. Évitez les bibliothèques qui n'ont pas de documentation d'accessibilité.

Testez la conformité de votre site

Scannez votre site et obtenez un rapport détaillé avec recommandations IA.

Scanner mon site - 15€