Accessibilite Next.js : guide RGAA complet
Guide complet pour rendre vos applications Next.js accessibles selon le RGAA : SSR, App Router, next/image, gestion du focus et checklist.
1. Introduction : Next.js et les défis d'accessibilité
Next.js se distingue des applications React classiques par son architecture hybride. Contrairement à une SPA (Single Page Application) pure où tout le rendu est côté client, Next.js propose plusieurs stratégies de rendu : SSR (Server-Side Rendering), SSG (Static Site Generation), ISR (Incremental Static Regeneration) et streaming avec React Suspense.
Cette flexibilité est un atout pour la performance et le SEO, mais elle crée des situations complexes pour l'accessibilité. Quand le HTML est généré côté serveur, les technologies d'assistance reçoivent un document complet dès le chargement initial — c'est un avantage. Mais les navigations subséquentes sont gérées côté client par le router Next.js, ce qui signifie que les lecteurs d'écran ne sont pas informés du changement de page.
L'introduction de l' App Router dans Next.js 13 a modifié en profondeur la façon de structurer les applications. Les Server Components, les layouts imbriqués, les fichiers spéciaux (loading.tsx, error.tsx, not-found.tsx) et le streaming introduisent de nouveaux patterns qui ont chacun des implications pour l'accessibilité.
Le Pages Router, encore largement utilisé, présente d'autres défis : l'absence de metadata API native oblige à utiliser des packages tiers comme next-seo, et la gestion du focus entre les pages nécessite une configuration manuelle via le composant _app.tsx.
Enfin, le streaming (activé par défaut avec l'App Router et Suspense) fait apparaître le contenu progressivement. Si un lecteur d'écran commence à lire une page dont le contenu n'est pas encore entièrement chargé, l'utilisateur peut manquer des informations. Il est essentiel de signaler les états de chargement avec les attributs ARIA appropriés.
2. Erreurs d'accessibilité courantes en Next.js
Voici les problèmes d'accessibilité les plus fréquents dans les projets Next.js, et pourquoi ils posent problème.
2.1. next/image sans attribut alt pertinent
Le composantnext/imagerend l'attribut alt obligatoire en TypeScript, mais beaucoup de
développeurs passent une chaîne vide (alt="") ou un texte
générique ("image", "photo") pour supprimer
l'erreur de compilation. Une image informative sans alternative
textuelle pertinente est invisible pour les utilisateurs de lecteurs
d'écran, ce qui viole le critère RGAA 1.1.
2.2. Attribut lang manquant ou incorrect sur la balise html
Dans l'App Router, l'attribut lang se définit dans le
fichierapp/layout.tsxracine. Oublier cet attribut ou le définir de manière incohérente
(par exemple "en" pour un contenu en français) empêche les
lecteurs d'écran de prononcer correctement le texte. Un lecteur
d'écran configuré en français qui rencontre un document déclaré
en anglais va tenter de lire le texte avec une prononciation
anglaise, rendant le contenu incompréhensible.
2.3. Layout shift perturbant les lecteurs d'écran
Les Cumulative Layout Shifts (CLS) ne sont pas seulement un problème
de performance. Quand le contenu se déplace pendant le chargement
(images sans dimensions, polices qui changent, composants chargés
dynamiquement), les technologies d'assistance peuvent perdre le
contexte. L'utilisateur qui naviguait dans une section se
retrouve soudainement dans une autre partie de la page sans
comprendre ce qui s'est passé. Next.js génère automatiquement
les dimensions des images avec next/image, mais les composants
chargés dynamiquement avecnext/dynamicsans placeholder peuvent provoquer des shifts importants.
2.4. Changement de route sans gestion du focus
C'est le problème d'accessibilité le plus critique et le
plus ignoré dans les applications Next.js. Lors d'une
navigation client-side (clic sur unnext/link), le contenu de la page change mais le focus reste sur le lien
cliqué ou se perd complètement. Un utilisateur de lecteur d'écran
ne reçoit aucune indication qu'une nouvelle page a été chargée.
Il doit naviguer manuellement pour découvrir le nouveau contenu.
C'est équivalent à ouvrir un livre à une nouvelle page sans le
dire à quelqu'un qui ne voit pas.
2.5. Server Components et logique d'accessibilité
Les React Server Components ne peuvent pas utiliser d'état,
d'effets ou de refs. Or, de nombreux patterns d'accessibilité
nécessitent de la logique côté client : gestion du focus, toggle
aria-expanded, trap du focus dans une modale, annonces live regions.
L'erreur courante est de tenter d'implémenter ces patterns
dans un Server Component, ce qui échoue silencieusement ou provoque
une erreur de compilation. La solution n'est pas de tout
transformer en Client Components, mais d'identifier précisément
quelles parties de l'interface nécessitent de l'interactivité
et de les isoler dans des composants marqués"use client".
3. Bonnes pratiques avec exemples de code
3.1. next/image avec texte alternatif
Le composant Image de Next.js optimise automatiquement les images (formats, tailles, lazy loading), mais l'accessibilité dépend entièrement de l'attribut alt que vous fournissez. Distinguez toujours les images informatives des images décoratives.
3.2. Metadata API pour des titres de page accessibles
Le titre de la page est le premier élément lu par un lecteur d'écran. Il doit être unique, descriptif et suivre un schéma cohérent. La Metadata API de Next.js (App Router) simplifie cette gestion avec l'export statique ou la fonction generateMetadata pour les pages dynamiques.
3.3. Gestion du focus au changement de route
Note : le Pages Router de Next.js incluait un route announcer intégré (next-route-announcer). L'App Router ne l'inclut pas encore — vous devez donc implémenter votre propre composant. Placez-le dans votre layout racine pour qu'il s'applique à toutes les navigations.
3.4. États de chargement accessibles avec loading.tsx
Le fichier loading.tsx de Next.js affiche automatiquement un fallback pendant le chargement d'une page. Pour que les technologies d'assistance informent l'utilisateur, utilisez aria-busy et une annonce live region.
3.5. Gestion d'erreur accessible avec error.tsx
Le fichier error.tsx capture les erreurs de rendu. L'erreur doit être annoncée aux technologies d'assistance et proposer une action de récupération accessible.
3.6. next/link et navigation client-side accessible
Le composant Link de Next.js effectue une navigation côté client (prefetching + changement de route sans rechargement complet). Pour l'accessibilité, assurez-vous que chaque lien a un intitulé explicite et que les liens ouvrant un nouvel onglet le signalent.
3.7. Server vs Client Components pour l'accessibilité
La règle est simple : gardez la structure sémantique HTML dans les Server Components et isolez la logique interactive dans les Client Components. Cela réduit la quantité de JavaScript côté client tout en conservant les patterns d'accessibilité nécessaires.
4. Critères RGAA clés pour Next.js
Parmi les 106 critères du RGAA 4.1.2, voici ceux qui sont particulièrement impactés par l'architecture Next.js et les choix techniques du framework.
Chaque image porteuse d'information a-t-elle une alternative textuelle ?
Thématique : Images
Le composantnext/imageexige un attribut alt en TypeScript, mais il faut s'assurer
que le texte est pertinent et non générique. Les images
décoratives doivent avoir alt="" et idéalement
aria-hidden="true". Attention aux images générées
dynamiquement (OG images, avatars) dont le alt est souvent
oublié dans les templates.
Chaque page web est-elle définie par un type de document ?
Thématique : Éléments obligatoires
Next.js génère automatiquement le doctype HTML5 dans le rendu serveur. Ce critère est naturellement satisfait avec le framework. Cependant, vérifiez que votre configuration n'altere pas le rendu initial (certains middleware de transformation HTML peuvent corrompre le doctype).
Pour chaque page web, le code source généré est-il valide ?
Thématique : Éléments obligatoires
Next.js génère du HTML valide, mais les erreurs de balisage viennent souvent de votre code : balises p imbriquées dans des p (React transforme les div en p dans certains cas), attributs invalides, IDs dupliqués (fréquents avec les listes dynamiques sans clé unique). Utilisez le validateur W3C sur le HTML rendu côté serveur pour détecter ces problèmes.
Dans chaque page web, la langue par défaut est-elle présente ?
Thématique : Éléments obligatoires
Avec l'App Router, la langue se définit dansapp/layout.tsxsur la balise<html lang="fr">. Avec le Pages Router, utilisez le fichier_document.tsx. Pour les sites multilingues avecnext-intlouapp/[locale]/layout.tsx, vérifiez que le lang dynamique est toujours cohérent avec le
contenu affiché.
Chaque ensemble de pages dispose-t-il d'au moins deux systèmes de navigation ?
Thématique : Navigation
Next.js ne fournit pas de système de navigation pré-construit. Vous devez implémenter au moins deux des mécanismes suivants : menu de navigation, plan du site, moteur de recherche. Le composant Link de Next.js facilite la navigation interne, mais c'est à vous de structurer le menu avec les rôles ARIA corrects (nav, role="navigation", aria-label) et de fournir un lien d'évitement vers le contenu principal.
Un lien d'évitement ou d'accès rapide à la zone de contenu principal est-il present ?
Thématique : Navigation
Le lien d'évitement ("Skip to main content") doit être
le premier élément focusable de la page. Dans Next.js,
placez-le dans le layout racine, juste après l'ouverture de<body>, avec un lien pointant vers l'ID de votre balise main.
Utilisez les classes Tailwind sr-only et focus:not-sr-only pour
le rendre visible uniquement au focus clavier.
5. Outils et packages recommandés
Un écosystème d'outils permet de détecter, tester et prévenir les problèmes d'accessibilité dans vos projets Next.js. Voici les indispensables.
Metadata API native (App Router)
Depuis Next.js 13+, l'exportmetadataou la fonctiongenerateMetadataremplacent avantageusement next-seo pour la gestion des titres,
descriptions et balises Open Graph. La Metadata API est
type-safe, supporte l'héritage (template de titre), et
fonctionne nativement avec les Server Components.
Alternative Pages Router :
next-seo
@axe-core/react
Détecte automatiquement les violations d'accessibilité pendant le développement. S'intègre dans la console du navigateur et signale les problèmes directement dans le DOM. Limitez son usage au mode développement pour ne pas impacter les performances en production.
@testing-library/react
La philosophie de Testing Library encourage les tests basés sur
les rôles et les labels accessibles plutôt que sur les classes
CSS ou les data-testid. Les queriesgetByRole,getByLabelTextetgetByAltTextvérifient implicitement que votre composant est accessible. Si
votre test ne trouve pas l'élément, c'est probablement
que votre HTML n'est pas sémantique.
pa11y-ci
Outil en ligne de commande qui teste l'accessibilité de vos pages dans un pipeline CI/CD. Configurez-le pour scanner toutes vos routes Next.js à chaque pull request. pa11y-ci peut être configuré avec un fichier de configuration listant les URLs à tester et les règles à appliquer. Combinez-le avec le sitemap généré par Next.js pour couvrir automatiquement toutes les pages.
6. Checklist accessibilité Next.js
Utilisez cette checklist pour vérifier l'accessibilité de votre application Next.js avant chaque mise en production.
Structure et configuration
- L'attribut
langest défini sur la balise<html>dans le layout racine - Chaque page a un titre unique via la Metadata API (export metadata ou generateMetadata)
- Un lien d'évitement "Aller au contenu principal" est present dans le layout racine
- La balise
<main>a un ID (main-content) pour le lien d'évitement - La hiérarchie des titres (h1-h6) est logique et sans saut de niveau sur chaque page
Images et médias
- Chaque composant next/image informatif a un attribut alt descriptif
- Les images décoratives ont alt="" et aria-hidden="true"
- Les dimensions width/height sont spécifiées pour éviter le layout shift
Navigation et routing
- Le focus est déplacé vers le contenu principal à chaque changement de route
- Le titre de la page est annoncé aux lecteurs d'écran lors des navigations client-side
- Les liens next/link ont des intitulés explicites (pas de "cliquez ici" ou "en savoir plus" sans contexte)
- Les menus de navigation utilisent la balise
<nav>avec un aria-label descriptif
États de chargement et erreurs
- Les fichiers loading.tsx utilisent role="status" et aria-busy="true"
- Les fichiers error.tsx utilisent role="alert" et déplacent le focus vers le message d'erreur
- Les fallbacks Suspense incluent un texte informatif (pas seulement un spinner visuel)
- La page not-found.tsx propose des alternatives de navigation (lien accueil, recherche)
Interactivité et composants
- Les éléments interactifs (modals, dropdowns, accordions) sont dans des Client Components avec la gestion du focus appropriée
- Tous les éléments interactifs sont utilisables au clavier (Enter, Espace, Échap, flèches)
- Les formulaires ont des labels associés avec htmlFor et des messages d'erreur liés par aria-describedby
- Le piège du focus est évité : l'utilisateur peut toujours quitter un composant au clavier
Tests et CI/CD
- @axe-core/react est configuré en mode développement
- Les tests unitaires utilisent les queries accessibles de @testing-library/react (getByRole, getByLabelText)
- pa11y-ci est intégré dans le pipeline CI pour scanner les routes principales
- Des tests manuels avec un lecteur d'écran (VoiceOver, NVDA) sont effectués avant chaque release
Questions fréquentes
Next.js est-il accessible par defaut ?
Non. Next.js fournit des bases solides comme le rendu HTML cote serveur et la Metadata API, mais l'accessibilite depend entierement de votre implementation.
Faut-il utiliser next-seo ou la Metadata API native ?
Avec l'App Router, la Metadata API native couvre l'essentiel : title, description, canonical et Open Graph. next-seo n'est plus indispensable dans la majorite des cas.
Comment gerer le focus lors d'un changement de route en Next.js ?
Il faut deplacer le focus vers le contenu principal apres chaque navigation client-side, par exemple avec usePathname(), useEffect() et un element cible portant tabindex='-1'.
Les Server Components posent-ils des problemes d'accessibilite ?
Non par eux-memes. Les enjeux apparaissent surtout quand une logique interactive a11y doit etre geree cote client : focus, toggles, modales ou annonces live.
Le streaming SSR de Next.js affecte-t-il les lecteurs d'ecran ?
Oui, si vous n'annoncez pas correctement les etats de chargement. Utilisez aria-busy et des regions aria-live quand le contenu apparait progressivement.
next/image genere-t-il un attribut alt automatiquement ?
Non. Le composant exige un alt, mais ne genere ni la bonne alternative ni le bon niveau de detail a votre place.
Comment tester l'accessibilite d'une application Next.js ?
Combinez des tests automatises avec axe et testing-library, puis des verifications manuelles au clavier et avec un lecteur d'ecran.
Le middleware Next.js a-t-il un impact sur l'accessibilite ?
Indirectement oui, si vos redirections de langue ou de contexte rendent un contenu incoherent avec l'attribut lang de la page.
Testez l'accessibilite de votre application Next.js
RGAA Scanner detecte automatiquement les problemes d'accessibilite de votre site Next.js et genere un rapport detaille avec les criteres RGAA concernes.
Scanner mon site gratuitement