Le contraste et la couleur
Deux exigences qu'on confond : l'information ne doit pas tenir à la seule couleur, et le texte doit être assez contrasté. Les seuils du RGAA se comptent en pixels rendus, et le gras bascule à 18,5 px.
3 critères RGAA en jeu
Essayez-le
1. Ce que la couleur porte toute seule
Version fautive — vert pour conforme, rouge pour non conforme
- Critère 1.1
- Critère 3.2
- Critère 8.3
Version corrigée — la couleur double un mot et un symbole
- Critère 1.1 conforme
- Critère 3.2 non conforme
- Critère 8.3 conforme
En niveaux de gris, la colonne de gauche ne dit plus rien : son information tenait à la seule couleur. Le passage en gris n'est pas une simulation de daltonisme — c'est un contrôle grossier, et il suffit à révéler le défaut.
2. La même couleur, cinq verdicts
3 anomalies restent à traiter.
3 anomalies restent à traiter.
3 anomalies restent à traiter.
3 anomalies restent à traiter.
Cochez « Retirer les couleurs » : la liste de gauche perd son information, celle de droite la garde. Puis lancez la mesure — les cinq échantillons portent la même couleur, et n’obtiennent pas le même verdict, parce que le seuil, lui, dépend de ce qu’on mesure.
Cette démo existe aussi en page autonome.
L’erreur courante
Deux fautes, sur le même écran, et on ne les répare pas de la même façon.
/* À ne pas faire : le lien ne se distingue que par sa couleur */
a {
color: #1b6ac9;
text-decoration: none;
}
/* À ne pas faire : « c'est du gras, donc c'est du grand texte » */
.avertissement {
font-size: 1rem;
font-weight: 700;
color: #8f8779;
} Le lien sans soulignement au milieu d’un paragraphe est un lien pour qui distingue le bleu du noir, et un mot ordinaire pour tous les autres. Ce n’est pas une affaire de contraste : le rapport peut être excellent, l’information reste donnée par la seule couleur.
Le second cas est l’erreur de seuil. 1rem se rend à 16 px avec les réglages par
défaut, donc en dessous des 18,5 px que le RGAA demande pour qu’un gras bénéficie
du seuil allégé. Ce texte relève de 4,5:1, il plafonne à 3,5:1, et l’auteur croit
être conforme parce qu’il l’a vu passer dans un vérificateur réglé sur « large
text ».
Trois variantes, aussi répandues :
- Le champ en erreur signalé par une bordure rouge seule. Qui ne voit pas le rouge ne voit pas d’erreur, et cherche pourquoi le formulaire refuse de partir.
- La légende d’un graphique réduite à des pastilles de couleur. Les courbes deviennent interchangeables ; il faut une étiquette, un motif ou un repère.
- Le texte d’indication d’un champ (
placeholder) gris très clair. C’est du texte : il relève entièrement du critère 3.2, comme le reste de la page.
Le code, pas à pas
1. Deux exigences, deux réparations
Le critère 3.1 porte sur l’information : ce que la couleur dit, autre chose doit le dire aussi. Le critère 3.2 porte sur la lisibilité : ce qui est écrit doit se détacher de son fond. Un même élément peut satisfaire l’un et manquer l’autre, dans les deux sens.
a {
color: var(--action); /* 3.2 : le rapport contre le fond */
text-decoration: underline; /* 3.1 : l'indice qui ne dépend pas de la couleur */
text-underline-offset: 0.2em;
} Le référentiel n’impose pas le soulignement — il impose que l’information ne tienne pas à la seule couleur. Un poids typographique, une icône, un repère de forme, un mot ajouté font aussi bien, à condition d’être visibles. Le soulignement a seulement l’avantage d’être compris sans apprentissage.
2. Les seuils, et la mesure en pixels rendus
Le critère 3.2 pose quatre cas, et c’est la taille restituée qui les départage :
| Texte | Seuil |
|---|---|
| Sans effet de graisse, restitué à moins de 24 px | 4,5:1 |
| En gras, restitué à moins de 18,5 px | 4,5:1 |
| Sans effet de graisse, restitué à 24 px ou plus | 3:1 |
| En gras, restitué à 18,5 px ou plus | 3:1 |
Le seuil du gras est à 18,5 px, et c’est là qu’on se trompe. Le WCAG énonce ces tailles en points — 18 pt, et 14 pt en gras ; le RGAA les convertit en pixels rendus. Lire ce « 14 » comme des pixels revient à accorder le seuil de 3:1 à des textes qui relèvent de 4,5:1, c’est-à-dire à presque tous les gras d’une interface.
Le critère s’applique aussi au texte en image, aux sous-titres et au texte
incrusté dans une vidéo. Il ne s’applique pas au texte d’un logo ou d’une marque,
au texte purement décoratif, ni à un élément d’interface inactif — un bouton disabled, par exemple.
3. Mesurer ce qui est rendu, pas ce qui est déclaré
const style = getComputedStyle(element);
style.fontSize; // « 16px », quelle que soit l'unité déclarée
style.fontWeight; // « 700 »
style.color; // « rgb(143, 135, 121) » getComputedStyle résout les em, les rem, les pourcentages et les héritages :
c’est la seule valeur qui corresponde à ce que le référentiel appelle la taille
restituée. Un font-size: 0.875em dans un conteneur déjà réduit descend plus bas
qu’on ne l’avait prévu, et bascule sous un seuil sans que la feuille de styles le
montre.
Deux situations résistent à toute mesure automatique, la nôtre comprise : un fond semi-transparent, et un texte posé sur une image ou un dégradé. Il faut alors reprendre le calcul à la main, sur la zone la moins favorable — c’est ce que dit le glossaire pour la couleur contiguë d’un dégradé.
4. Les composants d’interface : 3:1, dans chaque état
Le critère 3.3 est celui qu’on oublie. Il ne parle pas de texte mais des couleurs d’un composant d’interface et des éléments graphiques porteurs d’information, comparées à la couleur d’arrière-plan contiguë — celle qui touche le bord extérieur du composant.
.champ {
border: 1.5px solid var(--bordure); /* 3:1 contre le fond de la page */
}
.champ:focus-visible {
outline: 2px solid var(--focus); /* un état, donc à mesurer aussi */
outline-offset: 2px;
} Ce qui relève de ce critère : la bordure qui rend un champ repérable, la coche d’une case, la position d’un interrupteur, l’indicateur de focus quand vous l’avez redessiné, les segments d’un graphique dont la couleur est nécessaire à la compréhension.
Ce qui n’en relève pas, le référentiel le dit expressément : un composant inactif, un composant dont l’apparence reste celle du navigateur sans aucune retouche, et un composant que sa position, sa taille ou son texte suffisent à identifier sans la couleur.
5. Décidez-le dans la palette, pas dans les composants
Le contraste ne se rattrape pas composant par composant. Une couleur qui échoue échoue partout où elle sert, et corriger trois cents écrans un par un n’aboutit jamais. Fixez les couples texte/fond une fois, au niveau des jetons, et vérifiez les couples — pas les couleurs isolées.
Les tests admettent une porte de sortie : un mécanisme qui permet d’afficher les contenus avec un rapport conforme. Elle est plus étroite qu’elle n’en a l’air. Le glossaire exige que ce mécanisme conserve à l’identique les contenus et les fonctionnalités, et qu’il soit lui-même conforme aux critères 3.2 et 3.3 sans recourir à un autre mécanisme. Un thème « contraste élevé » à moitié tenu ne sauve rien.
Au clavier
Le contraste ne se navigue pas : ces touches sont celles de la démo. Le clavier croise pourtant le sujet en un point, et c’est le plus souvent manqué — le style de focus.
| Touche | Effet |
|---|---|
| Tab | Amène le focus sur la case à cocher, puis sur le champ, puis sur le bouton de mesure. |
| Espace | Coche ou décoche « Retirer les couleurs ». |
| Entrée / Espace | Sur le bouton, relance la mesure des styles rendus. |
Tabulez sur le champ de la démo. Le cas particulier du critère 3.3 vise un composant dont l’apparence est gérée par les styles natifs du navigateur sans aucune modification par l’auteur ; ce champ-là est restylé — bordure, rayon, fond, espacement — et seule son indication de focus reste native. La condition n’est donc remplie que pour ce contour, et dès que vous le redessinez, il devient un état à mesurer, à 3:1 au moins. Sa bordure, elle, se mesure dans tous les cas : c’est ce que fait la ligne « Champ de saisie » du tableau.
Ce que le lecteur d’écran restitue
Rien. Aucun lecteur d’écran n’annonce un rapport de contraste, et aucun ne restitue la couleur dans la lecture courante — NVDA et JAWS savent la dire sur commande, personne ne l’entend en lisant. C’est précisément l’argument du critère 3.1 : une information qui n’existe qu’en couleur n’existe pas du tout pour qui écoute la page. La liste fautive de la démo se lit « Critère 1.1, Critère 3.2, Critère 8.3 » — trois intitulés, aucun état. La liste corrigée se lit « Critère 3.2, non conforme ».
La formulation varie d’un lecteur à l’autre, mais la lecture courante laisse le même trou. Si vous écoutez une page et que l’état, la sélection, l’erreur ou la destination ne s’entendent nulle part alors qu’ils se voient à l’écran, l’information était dans la couleur. C’est le contrôle le plus rapide qui soit pour le critère 3.1 — et il ne dit rien du critère 3.2, qui ne se vérifie qu’à la mesure.
Checklist
- Doubler toute information portée par la couleur : un mot, une forme, un symbole.
- Vérifier les liens en contexte de texte : couleur seule, jamais.
- Mesurer sur la taille restituée, pas sur l’unité déclarée.
- Retenir 18,5 px pour le gras et 24 px pour le reste, avant d’appliquer 3:1.
- Mesurer les bordures, coches et indicateurs de focus redessinés à 3:1.
- Reprendre à la main tout texte posé sur une image, un dégradé ou un fond translucide.
- Fixer les couples de couleurs dans les jetons, pas dans chaque composant.
Les critères RGAA en jeu
- Critère 3.1 — Information donnée par la couleur
Un lien, un champ en erreur ou un statut signalés par la seule couleur ne disent rien à qui ne la perçoit pas : il faut un second indice, un mot, une forme ou un soulignement.
- Critère 3.2 — Contraste du texte
Le seuil dépend de la taille restituée et de la graisse : 4,5:1 par défaut, 3:1 à partir de 24 px, ou de 18,5 px en gras. Un gras de 16 px relève donc du seuil le plus exigeant.
- Critère 3.3 — Contraste des composants d’interface
Bordure, coche, indicateur de focus : ce sont les couleurs du composant, à 3:1 contre l'arrière-plan contigu et dans chacun de ses états — un champ qui passe au repos échoue souvent au focus.
Vérifiez votre composant avec l'extension
Pour aller plus loin
- Critère 3.1 — Information donnée par la couleur et 3.2 — Contraste du texte : les tests, un par un.
- Critère 3.3 — Contraste des composants d’interface : celui qu’on découvre en fin d’audit.
- « Contraste » au glossaire : la formule officielle, et ce que la mesure recouvre exactement.
- Les liens : l’endroit où le critère 3.1 se joue le plus souvent dans une page.
- Les champs de formulaire : bordures, états d’erreur et focus, tous concernés par le critère 3.3.
Sources
- WCAG — Understanding 1.4.1 Use of Color — pourquoi la couleur seule ne suffit jamais
- WCAG — Understanding 1.4.3 Contrast (Minimum) — l’origine des seuils 4,5:1 et 3:1
- WCAG — Understanding 1.4.11 Non-text Contrast — les composants d’interface et les éléments graphiques
- W3C — Technique G18, procédure de calcul — la formule que le glossaire du RGAA reprend
- WebAIM — Contrast Checker — la vérification ponctuelle, quand la mesure automatique ne suffit pas