Voici un chiffre qui ne cesse de me revenir : dans le rapport WebAIM Million de 2025, le texte à faible contraste était l'erreur d'accessibilité la plus fréquente du web, présente sur 79,1 % du million de pages d'accueil les plus consultées. Pas le texte alternatif manquant. Pas les boutons sans libellé. Le contraste. Le problème d'accessibilité le plus détecté au monde, ce sont deux couleurs trop semblables, et presque toutes les équipes qui le livrent n'en ont aucune idée.
J'ai moi-même livré ce bug. Il y a des années, j'ai construit un tableau de bord « haut de gamme » avec un élégant texte gris #9CA3AF sur blanc, validé par tout le monde dans la pièce parce qu'il avait l'air raffiné sur un écran Retina flambant neuf dans une salle de réunion sombre. Un ticket de support est arrivé une semaine plus tard, d'un utilisateur dans un train en plein soleil qui ne pouvait littéralement pas lire les libellés. Le texte était à environ 2.6:1. Les WCAG demandent 4.5:1. Cet écart est tout le sujet de cet article.
Ce qu'est réellement un rapport de contraste WCAG
Un rapport de contraste WCAG est un nombre unique qui décrit à quel point deux couleurs diffèrent en luminosité, exprimé sous forme de rapport allant de 1:1 à 21:1. Blanc sur blanc, c'est 1:1 (invisible). Noir pur sur blanc pur, c'est 21:1 (le maximum). Tout ce que vous concevez se situe quelque part entre les deux, et les WCAG fixent le plancher sous lequel vous n'avez pas le droit de descendre.
La chose cruciale à intégrer tôt : le contraste, c'est la luminance, pas le fait que les couleurs « aient l'air différentes ». Le rouge et le vert paraissent radicalement différents à la plupart des gens, mais un rouge saturé (#FF0000) sur un vert saturé (#008000) ne se situe qu'à environ 1.3:1, parce qu'ils portent presque la même luminosité. Pour une personne atteinte de daltonisme rouge-vert, ou pour quiconque jette un œil sur un écran de mauvaise qualité, cette association est de la bouillie. Votre œil est trompé par la teinte ; la formule de contraste, non.
La formule, en termes simples
Le rapport se calcule comme (L1 + 0.05) / (L2 + 0.05), où L1 est la luminance relative de la couleur la plus claire et L2 celle de la plus sombre. Vous ne le calculerez presque jamais à la main, mais comprendre les deux étapes vous explique pourquoi votre intuition vous égare.
D'abord, la luminance relative de chaque couleur est obtenue en prenant ses canaux rouge, vert et bleu, en les « linéarisant » (en annulant la courbe gamma que les écrans appliquent, selon la règle voulant que les canaux inférieurs ou égaux à 0.03928 soient divisés par 12.92, et les plus élevés passés par ((c + 0.055) / 1.055) ^ 2.4), puis en les pondérant : 0.2126 pour le rouge, 0.7152 pour le vert et 0.0722 pour le bleu. Ces poids ne sont pas arbitraires. L'œil humain est extraordinairement sensible au vert et presque aveugle au bleu en comparaison.
C'est l'enseignement le plus utile de ce calcul : le vert porte environ dix fois la luminosité perçue du bleu. Voilà pourquoi le texte bleu pur sur fond noir est pénible et passe à peine, tandis que la même « obscurité » de vert se lit très bien. Voilà pourquoi vos liens bleus sur fond sombre paraissent faibles, quelle que soit la saturation que vous leur donnez. Si vous ne retenez qu'une chose de la formule, retenez les poids.
Le + 0.05 du rapport est une constante qui modélise la lumière ambiante réfléchie par l'écran, de sorte que même des noirs théoriquement parfaits ne produisent jamais un rapport infini. C'est la raison pour laquelle les rapports de contraste plafonnent à 21:1.
Les trois seuils que vous devez connaître
Les WCAG (Web Content Accessibility Guidelines, maintenues par le W3C) définissent un petit jeu de nombres. Mémorisez-les et vous couvrez la grande majorité du travail réel.
- 4.5:1 — le minimum pour le texte courant au niveau AA. C'est le chiffre de référence. Si vous ne visez qu'une valeur, visez celle-ci.
- 3:1 — le minimum pour le grand texte en AA, et aussi le minimum pour les éléments d'interface non textuels et les graphiques (j'y reviens plus bas).
- 7:1 — le texte normal au niveau AAA, le palier renforcé pour les personnes malvoyantes. Le grand texte en AAA a besoin de 4.5:1.
Remarquez la régularité : chaque niveau correspond grosso modo au suivant. Le grand texte en AA et le non-texte partagent le 3:1 ; le texte normal en AA et le grand texte en AAA partagent le 4.5:1. C'est moins à retenir qu'il n'y paraît.
AA contre AAA : que devez-vous réellement ?
AA est la norme du monde réel. C'est celle que citent l'Acte européen sur l'accessibilité, les règlements à l'amiable liés à l'ADA aux États-Unis, la Section 508, et pratiquement tous les contrats de marché public. Quand un juriste ou un auditeur dit « conforme WCAG », il parle du AA. Le AAA est le palier or, et les recommandations elles-mêmes précisent explicitement que la conformité AAA n'est pas exigée comme politique générale pour des sites entiers, en partie parce que certains contenus ne peuvent tout simplement pas atteindre le 7:1 sans paraître cassés.
Mon avis honnête après des années de pratique : concevez le texte courant pour franchir le AA confortablement, puis traitez le AAA comme un objectif que vous atteignez pour le contenu qui compte le plus — la colonne de lecture principale d'un article, les messages d'erreur, tout ce qu'un utilisateur stressé ou malvoyant doit déchiffrer sous pression. Courir après le 7:1 sur chaque légende et chaque libellé désactivé est un combat perdu d'avance qui aplatit toute votre palette en noir sur blanc.
Texte normal contre grand texte — et le piège qui s'y cache
Les WCAG sont plus indulgents avec le grand texte (3:1 au lieu de 4.5:1) parce que des lettres plus grandes et plus épaisses restent lisibles à contraste plus faible. Mais la définition de « grand » est précise et tout le monde s'y trompe sans cesse.
- Grand = 18 pt et plus, soit 24 px en graisse normale.
- Ou 14 pt et plus, soit environ 18,5 px, si le texte est en gras.
La conversion qui piège tout le monde est 1 pt = 1,333 px, et c'est pourquoi 18 pt devient 24 px et 14 pt devient ~18,5 px. Ainsi un titre normal de 19px n'est pas du grand texte au sens des WCAG — il doit toujours le 4.5:1 complet. Un libellé en gras de 16 px n'est pas non plus du grand texte. J'ai vu des maquettes « passer » dans la tête de quelqu'un parce que le titre « avait l'air gros », alors qu'en pixels il se situait juste sous le seuil et exigeait le rapport plus strict. En cas de doute, tenez le corps de texte et les sous-titres au 4.5:1 et ne réclamez la dérogation à 3:1 que pour les caractères d'affichage réellement grands.
Le contraste du non-texte : le critère que tout le monde oublie (1.4.11)
C'est là que la plupart des équipes par ailleurs soigneuses échouent. WCAG 2.1 a ajouté le critère de succès 1.4.11, Contraste du non-texte, qui exige 3:1 pour deux catégories qui n'ont rien à voir avec la lecture :
- Les composants d'interface — la frontière visuelle d'un contrôle qui vous indique qu'il existe et dans quel état il se trouve. La bordure d'un champ de saisie, le contour d'une case à cocher décochée, l'anneau de focus autour d'un bouton, le rail d'un interrupteur.
- Les objets graphiques — les parties d'icônes, de graphiques et de diagrammes nécessaires à leur compréhension. La ligne d'une courbe miniature, les parts d'un camembert, la forme d'une icône d'avertissement.
La violation classique : un champ de recherche qui n'est qu'une boîte #FFFFFF avec une bordure de 1 px gris clair #E5E7EB sur une page blanche. Cette bordure tourne autour de 1.2:1. Les utilisateurs voyants mais malvoyants ne peuvent littéralement pas trouver où cliquer. Le texte d'invite pâle et les contours de boutons fantômes échouent de la même manière. La décoration pure est exemptée, tout comme le texte à l'intérieur du composant (celui-ci relève plutôt du 1.4.3) — mais l'élément qui signale « ceci est interactif » doit atteindre 3:1 par rapport à ce qui se trouve à côté.
Comment le mesurer — et comment le corriger
Le contraste ne se juge pas à l'œil. Il se mesure. Mon flux de travail quotidien :
- Dans le navigateur, ouvrez les DevTools et inspectez l'élément de texte. Chrome comme Firefox affichent le rapport de contraste directement dans le sélecteur de couleur, avec des coches pour AA et AAA, et tracent même une ligne dans l'espace colorimétrique indiquant le seuil que vous pouvez faire glisser.
- Pour vérifier une paire de codes hexadécimaux avant même qu'ils n'atteignent le code, utilisez un vérificateur dédié. Le générateur de palette de couleurs de ce site inclut un vérificateur de contraste WCAG, ce qui vous permet de valider les combinaisons pendant que vous les choisissez encore, au lieu de découvrir le problème lors d'un audit.
- Pour balayer des pages entières, lancez un outil automatisé. Mais connaissez sa limite : l'automatisation détecte le texte sur couleur pleine et passe à côté du texte posé sur des photos, des dégradés ou des superpositions semi-transparentes. Ceux-là, vous les vérifiez à la main.
Quand quelque chose échoue, résistez à l'envie de jouer sur la teinte. Changer la saturation bouge à peine le contraste ; changer la luminosité le bouge beaucoup. Concrètement :
- Assombrissez le premier plan ou éclaircissez l'arrière-plan jusqu'à franchir la ligne. Mon gris
#9CA3AFdu début devait passer à environ#6B7280sur blanc pour atteindre ~4.5:1 — même famille, juste quelques crans plus profond. - Pour du texte clair sur couleur, il est généralement plus rapide d'assombrir l'arrière-plan. Un libellé
#FFFFFFsur un bouton bleu#60A5FAéchoue ; passez le bouton à#2563EBet vous franchissez le AA sans toucher au texte. - Pour les graphiques et les icônes, ajoutez un fin contour plus sombre ou une légère teinte de fond plutôt que de vous acharner à rendre chaque aplat sombre.
Les erreurs que je vois dans les vraies équipes
- Valider sur un écran parfait. Un MacBook impeccable dans une pièce sombre flatte tout. Les vrais utilisateurs ont des reflets, des dalles bon marché, des filtres de lumière bleue, et un mode « nuit » qui réchauffe les blancs. Concevez pour la pire condition de visionnage plausible, pas pour la démo.
- Se fier à la teinte plutôt qu'à la luminance. Deux couleurs vives mais d'égale clarté (encore ce rouge sur vert) peuvent être invisibles pour les daltoniens tout en passant votre vérification intuitive. Calculez le nombre.
- Oublier le texte d'invite et les états désactivés. Les invites sont toujours du texte et doivent toujours du contraste si elles véhiculent un sens. Les contrôles désactivés sont réellement exemptés, mais n'abusez pas de cela pour cacher du contenu actif à faible contraste sous une apparence « désactivée ».
- Ignorer les superpositions. Du texte blanc sur une photo de bannière passe sur le coin sombre et échoue sur le ciel lumineux. Un voile — une couche sombre semi-opaque entre l'image et le texte — est la parade habituelle.
- Traiter le 4.5:1 comme un objectif plutôt qu'un plancher. Atterrir pile à 4.5:1 est fragile ; un designer qui retouche une nuance le casse à nouveau. Prévoyez de la marge.
Un mot sur l'avenir : WCAG 3 explore un modèle perceptuel appelé APCA qui juge le contraste davantage comme l'œil humain, en tenant compte ensemble de la taille et de la graisse du texte plutôt que d'un rapport fixe. C'est prometteur et à suivre, mais à ce jour, les rapports de cet article — confortés par la fiche « Understanding 1.4.3 » du W3C — sont ce qui vous rend conforme, juridiquement et pratiquement. Construisez selon eux, gardez-vous une marge, et mesurez au lieu de deviner. Les 79,1 % de sites qui échouent ont surtout échoué parce que personne n'a vérifié. Vérifier, c'est tout le métier.
Questions fréquentes
Quel est le rapport de contraste WCAG minimal pour le texte normal ?
Le texte courant a besoin d'un rapport de contraste d'au moins 4.5:1 par rapport à son arrière-plan pour atteindre le niveau AA des WCAG, qui est la norme à laquelle la plupart des lois et des contrats font référence. Le grand texte (18 pt/24 px en graisse normale, ou 14 pt/~18,5 px en gras) n'a besoin que de 3:1. Le niveau AAA, plus strict, porte le texte normal à 7:1 et le grand texte à 4.5:1.
Quelle est la différence entre le contraste WCAG AA et AAA ?
AA est la norme pratique, celle que citent les textes de loi : 4.5:1 pour le texte normal et 3:1 pour le grand texte. AAA est le niveau renforcé pour les personnes malvoyantes : 7:1 pour le texte normal et 4.5:1 pour le grand. Le W3C n'exige pas le niveau AAA sur l'ensemble d'un site, si bien que la plupart des équipes construisent leur texte courant en AA avec de la marge et réservent le AAA au contenu de lecture le plus critique.
Qu'est-ce qui compte comme grand texte selon les WCAG ?
Le grand texte fait 18 pt et plus (24 px) en graisse normale, ou 14 pt et plus (environ 18,5 px) s'il est en gras. La conversion est 1 pt = 1,333 px. Une erreur fréquente consiste à supposer qu'un titre qui paraît simplement gros entre dans la catégorie — un titre normal de 19 px ou 20 px reste sous les 24 px et doit atteindre le 4.5:1 complet du texte normal.
Les WCAG exigent-ils du contraste pour les boutons et les icônes, et pas seulement le texte ?
Oui. Le critère de succès 1.4.11 (Contraste du non-texte), ajouté dans WCAG 2.1, exige un rapport de 3:1 pour les contours de composants d'interface qui indiquent un état — bordures de champ, anneaux de focus, contours de case à cocher — et pour les objets graphiques comme les formes d'icônes et les éléments de graphique nécessaires à leur compréhension. La décoration pure est exemptée.
Comment corriger un texte qui échoue à la vérification de contraste ?
Ajustez la luminosité, pas la teinte ni la saturation — ces dernières ne bougent presque pas le rapport. Assombrissez le premier plan ou éclaircissez l'arrière-plan jusqu'à franchir le seuil ; pour du texte clair sur un bouton coloré, le plus rapide est généralement d'assombrir la couleur de fond. Mesurez le résultat avec un vérificateur de contraste plutôt qu'à l'œil, car les écarts de teinte trompent l'œil mais pas la formule de luminance.
Envie d'expérimenter avec les couleurs ?
Essayez notre générateur de palettes gratuit pour trouver l'harmonie parfaite — avec un vérificateur de contraste WCAG intégré.
Ouvrir le générateur