Technique27 août 20265 min

Écrire du code accessible : De la théorie à l'expérience utilisateur

En Bref : L'essentiel à retenir

  • La première règle ARIA : ne pas utiliser ARIA si le HTML natif suffit. Les pages avec ARIA ont 41% d'erreurs en plus.
  • Le code accessible repose sur trois piliers : HTML sémantique, gestion du focus clavier, et états ARIA pour le contenu dynamique.
  • Tester avec un lecteur d'écran est indispensable : les outils automatiques ne détectent que 30-50% des problèmes.
CodeHTMLARIADéveloppementSémantiqueRGAA

Un code techniquement conforme peut créer une expérience utilisateur désastreuse. À l'inverse, un code qui comprend les besoins réels des utilisateurs de technologies d'assistance offre une navigation fluide et intuitive.

Ce guide vous aide à passer de la conformité technique à l'expérience utilisateur réelle.

La première règle : HTML sémantique avant tout

Pourquoi le HTML natif prime

La « première règle d'ARIA » établie par le W3C est claire : n'utilisez pas ARIA si le HTML natif suffit.

Un <button> natif offre gratuitement :

  • Rôle « button » pour les lecteurs d'écran
  • Activation par Entrée et Espace
  • Focus clavier automatique
  • États disabled gérés

Un <div onclick> nécessite de tout réimplémenter manuellement, avec risque d'erreurs.

Les statistiques parlent

L'étude WebAIM sur un million de pages montre que les sites utilisant ARIA présentent 41% d'erreurs supplémentaires par rapport à ceux sans ARIA.

ARIA mal utilisé est pire qu'absent. Le HTML sémantique est votre fondation la plus solide.

Note

En 2025, l'accessibilité n'est plus optionnelle. Les standards WCAG 2.2 et l'EAA imposent une conformité qui passe d'abord par un HTML propre.

Structure sémantique d'une page

Les landmarks essentiels

Les landmarks permettent aux utilisateurs de lecteurs d'écran de naviguer rapidement entre les grandes sections :

CODE
<header>
  <nav aria-label="Navigation principale">...</nav>
</header>

<main>
  <article>
    <h1>Titre principal</h1>
    ...
  </article>
</main>

<aside aria-label="Articles connexes">...</aside>

<footer>...</footer>

Ces balises créent automatiquement des régions navigables. Pas besoin de role="banner" sur un <header> : c'est redondant.

Hiérarchie des titres

Les titres structurent le contenu et permettent la navigation par raccourci (touche H) :

CODE
<h1>Titre de la page (unique)</h1>
  <h2>Section principale</h2>
    <h3>Sous-section</h3>
    <h3>Autre sous-section</h3>
  <h2>Autre section principale</h2>

Erreurs fréquentes :

  • Sauter des niveaux (h1 puis h3)
  • Utiliser les titres pour le style plutôt que la structure
  • Plusieurs h1 par page (acceptable en HTML5, déconseillé pour l'accessibilité)

Astuce

Vérifiez la structure de vos titres avec notre outil d'audit qui détecte les sauts de niveaux et les titres vides.

Éléments interactifs accessibles

Boutons

Utilisez <button> pour les actions, <a> pour la navigation :

CODE
<!-- Action (ouvre modal, soumet formulaire) -->
<button type="button" onclick="openModal()">
  Ouvrir les paramètres
</button>

<!-- Navigation (change de page) -->
<a href="/parametres">
  Aller aux paramètres
</a>

Pour un bouton avec icône seule :

CODE
<button type="button" aria-label="Fermer">
  <svg aria-hidden="true">...</svg>
</button>

L'icône est masquée pour les lecteurs d'écran (aria-hidden), le label est fourni par aria-label.

Liens

Les liens doivent être explicites hors contexte :

CODE
<!-- Mauvais -->
<a href="/rapport.pdf">Cliquez ici</a>

<!-- Bon -->
<a href="/rapport.pdf">
  Télécharger le rapport annuel 2026 (PDF, 2.3 Mo)
</a>

Pour les liens qui ouvrent un nouvel onglet :

CODE
<a href="https://externe.com" target="_blank" rel="noopener">
  Site externe (s'ouvre dans un nouvel onglet)
</a>

Formulaires accessibles

Association label-champ

Chaque champ doit avoir un label associé programmatiquement :

CODE
<label for="email">Adresse email</label>
<input type="email" id="email" name="email" autocomplete="email">

Pour les champs avec instructions supplémentaires :

CODE
<label for="password">Mot de passe</label>
<input
  type="password"
  id="password"
  aria-describedby="password-help"
>
<span id="password-help">
  8 caractères minimum, 1 majuscule, 1 chiffre
</span>

Gestion des erreurs

Les erreurs doivent être liées aux champs et annoncées :

CODE
<label for="email">Adresse email</label>
<input
  type="email"
  id="email"
  aria-invalid="true"
  aria-describedby="email-error"
>
<span id="email-error" role="alert">
  L'adresse email n'est pas valide
</span>

Le role="alert" déclenche une annonce immédiate par le lecteur d'écran.

Groupes de champs

Les boutons radio et checkboxes doivent être groupés :

CODE
<fieldset>
  <legend>Mode de paiement</legend>

  <input type="radio" id="cb" name="paiement" value="cb">
  <label for="cb">Carte bancaire</label>

  <input type="radio" id="paypal" name="paiement" value="paypal">
  <label for="paypal">PayPal</label>
</fieldset>

Contenus dynamiques avec ARIA

États pour les composants interactifs

Pour un accordéon :

CODE
<button
  aria-expanded="false"
  aria-controls="section1-content"
>
  Section 1
</button>
<div id="section1-content" hidden>
  Contenu de la section...
</div>

Quand l'accordéon s'ouvre, JavaScript doit :

  1. Passer aria-expanded à true
  2. Retirer l'attribut hidden

Régions dynamiques (live regions)

Pour les notifications qui apparaissent sans action utilisateur :

CODE
<div aria-live="polite" aria-atomic="true">
  <!-- Le contenu injecté ici sera annoncé -->
</div>
  • aria-live="polite" : Annonce après la fin de la phrase courante
  • aria-live="assertive" : Interrompt immédiatement (à utiliser avec parcimonie)

Modales accessibles

Une modale correctement implémentée :

CODE
<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="modal-title"
>
  <h2 id="modal-title">Confirmer la suppression</h2>
  <p>Cette action est irréversible.</p>
  <button>Annuler</button>
  <button>Supprimer</button>
</div>

Le JavaScript doit :

  1. Déplacer le focus dans la modale à l'ouverture
  2. Piéger le focus dans la modale (Tab ne sort pas)
  3. Fermer avec Échap
  4. Restaurer le focus à l'élément déclencheur à la fermeture

Focus visible

Ne supprimez jamais l'outline sans alternative :

CODE
/* Mauvais */
:focus {
  outline: none;
}

/* Bon */
:focus {
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}

/* Encore mieux : focus-visible pour les utilisateurs souris */
:focus-visible {
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}

Ordre de tabulation

L'ordre de focus doit suivre l'ordre visuel logique. Évitez tabindex positif :

CODE
<!-- Mauvais : ordre imprévisible -->
<input tabindex="3">
<input tabindex="1">
<input tabindex="2">

<!-- Bon : ordre naturel du DOM -->
<input>
<input>
<input>

Utilisez tabindex="0" pour rendre focusable un élément non-interactif, tabindex="-1" pour permettre le focus programmatique sans Tab.

Note

Consultez notre guide ARIA pour approfondir les attributs ARIA et leur usage correct.

Tests indispensables

Tests automatisés

Intégrez axe-core dans votre CI/CD :

CODE
import AxeBuilder from '@axe-core/playwright';

test('Page accessible', async ({ page }) => {
  await page.goto('/');
  const results = await new AxeBuilder({ page }).analyze();
  expect(results.violations).toHaveLength(0);
});

Ces tests détectent 30-50% des problèmes.

Tests manuels obligatoires

Pour les 50-70% restants :

  1. Navigation clavier complète : Parcourez toute la page avec Tab
  2. Test lecteur d'écran : NVDA sur Windows, VoiceOver sur Mac
  3. Zoom 200% : Le contenu reste-t-il utilisable ?
  4. Désactivation CSS : La page reste-t-elle compréhensible ?

L'expérience utilisateur, objectif final

Le code accessible n'est pas une fin en soi. L'objectif est que des personnes réelles puissent utiliser votre site efficacement.

Un formulaire techniquement conforme mais avec des messages d'erreur incompréhensibles reste inutilisable. Un menu accessible au clavier mais avec un ordre de focus illogique reste frustrant.

Mettez-vous à la place de vos utilisateurs. Testez avec de vrais lecteurs d'écran. Écoutez les retours des personnes concernées.

Le code accessible de qualité ne se mesure pas en conformité WCAG mais en expérience utilisateur réussie.

Questions fréquentes

Sur quoi repose du code accessible ?

Sur trois piliers : un HTML sémantique qui donne aux éléments leur rôle natif, une gestion explicite du focus clavier à chaque changement d'état, et des attributs ARIA réservés à ce que le HTML ne sait pas exprimer, principalement les contenus qui changent sans rechargement.

Pourquoi préférer un bouton natif à un div cliquable ?

Parce que l'élément button apporte gratuitement quatre choses : le rôle annoncé aux technologies d'assistance, la prise de focus au clavier, l'activation par Entrée et par Espace, et la gestion de l'état désactivé. Un div doté d'un gestionnaire de clic n'en apporte aucune, il faut les réécrire une par une.

Comment vérifier qu'un composant est réellement accessible ?

En le parcourant au clavier sans souris, puis en l'écoutant avec un lecteur d'écran. Ces deux passages révèlent ce qu'aucune revue de code ne montre : un focus qui disparaît, un état annoncé à contretemps, un composant dont on ne peut plus sortir.

Votre site est-il conforme ?

Ne prenez pas de risques avec l'accessibilité. Lancez un audit complet de votre site en quelques minutes et obtenez un rapport détaillé des corrections à apporter.