Accessibilité & robustesse du UI¶
Ce n'est pas une checklist
L'accessibilité n'est pas une étape qu'on ajoute à la fin. C'est une série de décisions techniques qu'on prend tout au long de l'intégration.
Ce qui distingue un intégrateur compétent d'un outil qui génère du code : le code généré par l'IA passe rarement les audits d'accessibilité sans correction. Il produit du HTML qui fonctionne visuellement, mais ignore systématiquement ce qui n'est pas visible à l'écran.
Grand résumé¶
- Contraste et lisibilité
- Focus visible et navigation clavier
- Tailles de clic et états interactifs
- Structure sémantique
- Attributs d'accessiblité: Textes alternatifs, AREA, lien entre label et input
- Auditer avec Lighthouse et axe DevTools
Contraste et lisibilité¶
Les deux seuils à retenir (WCAG AA)¶
Le WCAG (Web Content Accessibility Guidelines) définit des ratios de contraste minimaux entre la couleur du texte et son arrière-plan.
| Type de contenu | Ratio minimal |
|---|---|
| Texte normal (moins de 18px) | 4.5 : 1 |
| Grand texte (18px+ ou 14px gras) | 3 : 1 |
| Éléments d'interface (icônes, bordures de champs) | 3 : 1 |
/* ❌ Problème fréquent : texte trop pâle sur fond clair */
.label {
color: #aaaaaa; /* ratio ~2.3:1 sur blanc : insuffisant */
}
/* ✅ Correction */
.label {
color: #767676; /* ratio ~4.5:1 sur blanc : seuil exact */
}
See the Pen DEMO Accessibilité - Contraste by TIM Montmorency (@tim-momo) on CodePen.
Vérifier le contraste directement dans DevTools¶
Chrome DevTools affiche le ratio de contraste directement dans le color picker :
- Inspecte un élément texte
- Clique sur la pastille de couleur dans le panneau CSS
- Le ratio s'affiche : un ✓ indique que le seuil AA est atteint, ✓✓ indique AAA

Petit exercice d'observation¶
- 1. Ouvre le wiki du cours, la page courante dans Google Chrome: https://tim-montmorency.com/compendium/582-211-web2/css/accessibilite.html#petit-exercice-dobservation
- 2. Si ce n'est pas le cas, mets le site en dark mode via cet icône en haut à droite:

- 3. Inspecte ce texte jaune ⬅️
- 4. Clique sur la pastille de couleur dans le panneau CSS
- 5. Observe le ratio de contraste... Quel est-il? Est-ce que ça passe les normes de lisiblité et d'accessibilité selon WCAG ?
- 6. Change maintenet le site en light mode via cet icône en haut à droite:

- 7. Inspecte ce texte jaune ⬅️
- 8. Clique sur la pastille de couleur dans le panneau CSS
- 9. Observe le ratio de contraste... Maintenant qu'est-il? Est-ce que ça passe les normes de lisiblité et d'accessibilité selon WCAG ?
Résumé constrate et lisibilité¶
See the Pen DEMO accessibilité: constrate by TIM Montmorency (@tim-momo) on CodePen.
Focus visible et navigation clavier¶
Pourquoi c'est important¶
Certains utilisateurs ne peuvent pas utiliser une souris : personnes avec des troubles moteurs, malvoyants qui utilisent un lecteur d'écran, utilisateurs avancés qui naviguent au clavier. Pour eux, le focus visible est le seul indicateur de leur position sur la page.
Le lien direct avec :focus-visible¶
Tu as vu :focus-visible dans la section précédente. C'est ici que son importance prend tout son sens :
/* ❌ Ce pattern est partout : et il brise l'accessibilité */
* {
outline: none;
}
/* ✅ La bonne approche */
:focus {
outline: none; /* retire l'outline au clic souris */
}
:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}
Ce que doit indiquer un état de focus¶
Un indicateur de focus accessible doit être :
- Visible : contraste suffisant avec le fond (ratio 3:1 minimum)
- Distinct : différent de l'état normal au repos
- Stable : ne disparaît pas trop vite, n'est pas masqué par un
overflow: hidden
/* Exemple d'un focus robuste */
.bouton:focus-visible {
outline: 2px solid #2d6a4f;
outline-offset: 3px;
/* outline-offset sépare le contour de l'élément
: évite qu'il se confonde avec la bordure */
}
See the Pen DEMO accessibilité: focus by TIM Montmorency (@tim-momo) on CodePen.
Tester soi-même¶
La méthode la plus rapide : pose ta souris et navigue avec Tab.
- Tab : avancer vers l'élément focusable suivant
- Shift+Tab : reculer
- Enter ou Space : activer un bouton ou un lien
Si tu perds ta position à un moment, c'est un problème d'accessibilité.
Tailles de clic et états interactifs¶
La taille minimale recommandée¶
Le WCAG 2.5.5 recommande une zone cliquable d'au moins 44 × 44 pixels pour les éléments interactifs, particulièrement sur mobile et écran tactile.
/* ❌ Icône cliquable trop petite */
.btn-icone {
width: 16px;
height: 16px;
}
/* ✅ Zone de clic étendue sans changer l'apparence visuelle */
.btn-icone {
width: 16px;
height: 16px;
padding: 14px; /* zone de clic : 44×44px: 16px+14px+14px=44px */
}
/* ✅ Ou avec min-width / min-height et centrer avec flexbox */
.btn-icone {
min-width: 44px;
min-height: 44px;
display: flex;
align-items: center;
justify-content: center;
}
Les trois états interactifs obligatoires¶
Un élément cliquable doit avoir un style distinct pour chacun de ces états :
.bouton {
background: #f5f4f0;
border: 1px solid #e0ddd6;
cursor: pointer;
}
/* 1. Survol souris */
.bouton:hover {
background: #e8e6e0;
border-color: #2d6a4f;
}
/* 2. Focus clavier */
.bouton:focus-visible {
outline: 2px solid #2d6a4f;
outline-offset: 3px;
}
/* 3. Clic / activation */
.bouton:active {
transform: scale(0.97);
background: #d8f3dc;
}
L'erreur la plus fréquente
Définir uniquement :hover et oublier :focus-visible et :active. Sur mobile, :hover n'existe pas : l'état :active est le seul feedback visuel disponible.
See the Pen DEMO accessibilité: états interactifs by TIM Montmorency (@tim-momo) on CodePen.
Structure HTML sémantique¶
Le HTML sémantique comme fondation¶
Un code accessible commence par un HTML qui utilise les bonnes balises pour les bons usages. Les lecteurs d'écran se fient à la sémantique pour annoncer le contenu aux utilisateurs.
<!-- ❌ Div soup : aucune information structurelle -->
<div class="header">
<div class="nav">
<div class="nav-item">Accueil</div>
<div class="nav-item">À propos</div>
</div>
</div>
<!-- ✅ Sémantique correcte -->
<header>
<nav>
<ul>
<li><a href="/">Accueil</a></li>
<li><a href="/a-propos">À propos</a></li>
</ul>
</nav>
</header>
Hiérarchie des titres¶
Les titres (h1 à h6) structurent la page comme une table des matières. Un lecteur d'écran peut naviguer directement d'un titre à l'autre.
<!-- ❌ Titres choisis pour leur taille, pas leur hiérarchie -->
<h1>Titre de page</h1>
<h3>Section importante</h3> <!-- on a sauté h2 -->
<h5>Sous-section</h5> <!-- on a sauté h4 -->
<!-- ✅ Hiérarchie logique -->
<h1>Titre de page</h1>
<h2>Section importante</h2>
<h3>Sous-section</h3>
ℹ️ Si tu veux un
h3qui ressemble visuellement à unh2, change le style CSS : ne change pas la balise.
Attributs d'accessibilité¶
Textes alternatifs via l'attribut alt¶
Toute image qui porte une information doit avoir un attribut alt descriptif. Une image purement décorative doit avoir un alt vide pour être ignorée par les lecteurs d'écran.
<!-- ❌ Alt manquant : le lecteur d'écran lit le nom du fichier -->
<img src="graphique-ventes-q3.png">
<!-- ❌ Alt inutile : répète ce que l'entourage dit déjà -->
<img src="logo.png" alt="image du logo">
<!-- ✅ Alt informatif -->
<img src="graphique-ventes-q3.png" alt="Ventes Q3:hausse:23% par rapport à Q2">
<!-- ✅ Image décorative : ignorée par les lecteurs d'écran -->
<img src="separateur-decoratif.png" alt="">
Attributs ARIA essentiels¶
Quand le HTML sémantique ne suffit pas à décrire l'intention d'un élément, les attributs ARIA (Accessible Rich Internet Applications) prennent le relais. Ils transmettent aux technologies d'assistance des informations que le code visuel ne peut pas exprimer seul.
Les quatre attributs les plus courants en intégration :
aria-label¶
Donne un nom explicite à un élément interactif quand son contenu textuel est absent ou insuffisant (ex. : un bouton avec seulement une icône).
<!-- ❌ Le lecteur d'écran annonce "bouton" sans contexte -->
<button><img src="fermer.svg"></button>
<!-- ✅ Le lecteur d'écran annonce "Fermer le menu" -->
<button aria-label="Fermer le menu"><img src="fermer.svg" alt=""></button>
aria-hidden¶
Masque un élément aux technologies d'assistance. Utile pour les icônes décoratives ou les éléments visuels redondants.
<!-- L'icône est décorative : le lecteur d'écran l'ignore -->
<span aria-hidden="true">★</span> Favori
aria-expanded¶
Indique si un élément dépliable (accordéon, menu) est ouvert ou fermé. Doit être mis à jour dynamiquement via JavaScript.
<button aria-expanded="false" aria-controls="menu-nav">
Menu
</button>
<nav id="menu-nav" hidden>...</nav>
role¶
Redéfinit le rôle sémantique d'un élément quand la balise HTML ne reflète pas son usage réel.
<!-- Une div utilisée comme bouton : le clavier ne fonctionnera pas
sans tabindex, mais le rôle aide les lecteurs d'écran -->
<div role="button" tabindex="0">Ajouter au panier</div>
Repères de navigation (landmarks)¶
Le document doit avoir une balise ARIA principale (main landmark).
Repères de navigation (landmarks)¶
Pour qu'un lecteur d'écran puisse sauter directement au contenu principal sans réécouter l'entête à chaque page, la page doit contenir une balise <main>. C'est ce qu'on appelle un landmark ARIA : un repère de navigation structurel.
Il est recommandé d'utiliser conjointement les balises HTML5 sémantiques et leurs équivalents ARIA, pour maximiser la compatibilité avec toutes les technologies d'assistance :
| Balise HTML5 | Équivalent ARIA |
|---|---|
<header> |
role="banner" |
<nav> |
role="navigation" |
<main> |
role="main" |
<footer> |
role="contentinfo" |
<!-- ✅ Structure robuste : HTML5 + ARIA -->
<header role="banner">...</header>
<nav role="navigation">...</nav>
<main role="main">...</main>
<footer role="contentinfo">...</footer>
Tip
En pratique, les navigateurs modernes reconnaissent bien les balises HTML5 seules. Ajouter le role ARIA reste une bonne habitude pour garantir la compatibilité avec les lecteurs d'écran plus anciens.
Règle d'or ARIA
N'utilise pas ARIA pour corriger un mauvais choix de balise sémantique. Si tu peux utiliser <button>, <nav> ou <a>, fais-le : c'est toujours préférable.
Liens entre champs <input> et étiquettes <label>¶
Tout champ de formulaire doit être explicitement lié à son étiquette via l'attribut for (sur le <label>) et id (sur le champ). Sans ce lien, le lecteur d'écran ne sait pas à quoi correspond le champ.
<!-- ❌ Label et champ non liés : le lecteur d'écran les annonce séparément -->
<label>Courriel</label>
<input type="email">
<!-- ✅ Lien explicite : cliquer sur le label active le champ -->
<label for="courriel">Courriel</label>
<input type="email" id="courriel">
Langue du document et texte des liens¶
- Langue de la page : permet au lecteur d'écran de prononcer correctement le contenu. Simple et souvent oublié.
- Liens explicites : Un lien qui dit "cliquez ici" ou "en savoir plus" est inutilisable hors contexte. Le texte du lien doit décrire la destination.
Auditer avec Lighthouse et axe DevTools¶
Deux outils, deux usages¶
Lighthouse (intégré à Chrome DevTools) donne un score global et une liste de problèmes avec leur impact. Idéal pour un audit rapide et une vue d'ensemble.
axe DevTools (extension Chrome) est plus précis sur les violations spécifiques du WCAG. Il indique exactement quel critère est violé et pourquoi.
En savoir plus sur le score d'accessiblité de LightHouse
Visitez la documentation (en français) de LightHouse sur le score de l'audit sur l'accessibilité
Comment lancer un audit Lighthouse¶
- Ouvre DevTools (
F12ouCmd+Option+I) - Onglet Lighthouse
- Coche Accessibility (décoche les autres pour aller plus vite)
- Clique Analyze page load
- Lis le rapport : chaque problème est expliqué avec sa cause et son impact
Ce que Lighthouse ne détecte pas¶
Lighthouse automatise environ 30 à 40% des vérifications d'accessibilité. Le reste requiert une vérification manuelle. Un score de 100 ne garantit pas une page accessible.
Ce qu'il ne peut pas détecter automatiquement :
- Si les textes alternatifs sont pertinents (il détecte leur absence, pas leur qualité)
- Si la navigation clavier est logique (ordre du focus)
- Si le contenu est compréhensible pour quelqu'un qui ne voit pas la page
Cette semaine (semaine 4), avant la remise
Tu auras à faire un audit d'accessibilité avec Lighthouse sur ton propre projet Solarix. L'objectif n'est pas d'atteindre 100 : c'est de comprendre chaque problème signalé et de pouvoir expliquer comment tu le corrigerais (ou comment tu l'as corrigé).
Démo en classe¶
La démo suivante présente une page avec des erreurs d'accessibilité intentionnelles. On va l'auditer ensemble avec Lighthouse et axe DevTools pour voir exactement ce que les outils détectent : et ce qu'ils manquent.
Résumé : Ce qu'un intégrateur doit toujours vérifier¶
| Quoi vérifier | Comment |
|---|---|
| Contraste texte / fond | DevTools color picker, ou WebAIM Contrast Checker |
| Focus clavier visible | Naviguer à la ++Tab ↹++ et observer |
| Zones cliquables ≥ 44px | Inspecter les dimensions dans DevTools |
| États hover, focus, active | Tester manuellement chaque état |
| Hiérarchie des titres | Onglet Accessibility dans DevTools |
| Textes alternatifs pertinents | Lire chaque alt à voix haute : est-ce utile? |
| Attributs ARIA présents et pertinents | Lire chaque attribut : est-ce qu'il compense un vrai manque sémantique? |
| Audit global | Lighthouse > Accessibility |