Comment calculer le ratio de contraste des couleurs (WCAG AA/AAA)
Le ratio de contraste des couleurs mesure à quel point une couleur de texte se démarque de son arrière-plan, sur une échelle de 1:1 (couleurs identiques) à 21:1 (noir pur sur blanc pur). Le WCAG 2.1 fixe des ratios minimaux pour qu’un texte soit considéré lisible : 4,5:1 pour le texte normal au niveau AA, le seuil que retiennent la plupart des audits d’accessibilité et des obligations légales.
La formule
Le ratio découle de la luminance relative de chaque couleur, pas de l’apparence de la couleur à l’écran. Quatre étapes transforment un code hexadécimal en valeur de luminance :
- Décomposez le hex en R, G, B et divisez chaque valeur par 255, pour obtenir un chiffre entre 0 et 1 par canal.
- Linéarisez chaque canal. Les écrans ne traduisent pas les valeurs de couleur en luminosité de façon linéaire, donc chaque canal reçoit une correction gamma : si la valeur est ≤ 0,03928, on la divise par 12,92 ; sinon on applique
((valeur + 0,055) / 1,055) ^ 2,4. - Pondérez et additionnez les canaux pour obtenir la luminance relative :
L = 0,2126 × R + 0,7152 × G + 0,0722 × B. Le vert reçoit le poids le plus élevé, l’œil humain y étant le plus sensible ; le bleu reçoit le plus faible. - Divisez la luminance la plus claire par la plus sombre, les deux augmentées de 0,05 :
(L_claire + 0,05) / (L_sombre + 0,05).
Ce + 0,05 final a un rôle précis : il empêche le ratio de s’envoler vers l’infini quand une des couleurs se rapproche du noir, et c’est la raison pour laquelle le noir pur sur blanc pur plafonne exactement à 21:1, pas à un chiffre bien plus grand.
Exemple détaillé : #767676 sur blanc
Cette paire gris sur blanc revient souvent dans la documentation du WCAG parce qu’elle se situe pile sur un seuil, ce qui en fait un bon cas à calculer à la main.
Étape 1. #767676 en RGB donne 118, 118, 118. Divisé par 255, cela donne 0,4627 pour chaque canal.
Étape 2. 0,4627 est au-dessus de 0,03928, on linéarise donc avec la formule gamma : ((0,4627 + 0,055) / 1,055) ^ 2,4 = 0,1810. Les trois canaux sont identiques ici, cette valeur s’applique donc à R, G et B à la fois.
Étape 3. Luminance : L = 0,2126 × 0,1810 + 0,7152 × 0,1810 + 0,0722 × 0,1810 = 0,1810. La luminance du blanc est 1,0 (chaque canal se linéarise exactement à 1).
Étape 4. Ratio : (1,0 + 0,05) / (0,1810 + 0,05) = 1,05 / 0,2310 = 4,545, arrondi à 4,54:1.
Ce chiffre se place juste au-dessus de la limite de 4,5:1 pour l’AA en texte normal, et juste au-dessus de la limite de 4,5:1 pour l’AAA en grand texte, mais bien en dessous du 7:1 exigé par l’AAA pour le texte normal. Une seule valeur hex, trois verdicts différents selon la taille du texte et le niveau visé.
Comment se comportent vraiment des paires de couleurs courantes
| Paire | Ratio | AA normal (4,5:1) | AAA normal (7:1) | AA grand (3:1) | AAA grand (4,5:1) |
|---|---|---|---|---|---|
#AAAAAA sur #FFFFFF | 2,32:1 | Échec | Échec | Échec | Échec |
#767676 sur #FFFFFF | 4,54:1 | Réussite | Échec | Réussite | Réussite |
#2563EB sur #FFFFFF | 5,17:1 | Réussite | Échec | Réussite | Réussite |
#333333 sur #FFFFFF | 12,63:1 | Réussite | Réussite | Réussite | Réussite |
Deux enseignements se dégagent de ce tableau. D’abord, un bleu moyennement saturé comme #2563EB (couleur fréquente pour les boutons et les liens) passe l’AA pour le texte courant, mais échoue totalement à l’AAA, donc un site qui vise l’AAA pour ses liens a besoin d’une teinte plus sombre. Ensuite, le gris clair populaire autour de #AAAAAA, souvent utilisé pour les placeholders, échoue à tous les seuils, y compris le minimum de 3:1 pour le grand texte, ce qui explique pourquoi le texte gris « discret » sur fond blanc revient si souvent dans les audits d’accessibilité.
Testez vos propres couleurs
Saisissez deux valeurs hex ci-dessous pour obtenir le ratio exact et voir quels niveaux WCAG elles atteignent, en direct, sans envoi de fichier ni appel serveur.
Portez ce vieux whisky au juge blond qui fume
Portez ce vieux whisky au juge blond qui fume
Erreurs fréquentes
Oublier que le grand texte a un seuil plus bas. Le WCAG définit le « grand texte » comme du 18pt (24px) en graisse normale ou du 14pt (18,66px) en gras et plus. Un titre de 24px ne demande que 3:1, pas 4,5:1, donc un design system qui applique la même règle de contraste à toutes les tailles de texte finit par rejeter des titres pourtant déjà conformes.
Tester le contraste du texte sans tester celui des composants d’interface. Le WCAG 1.4.11 fixe un minimum distinct de 3:1 pour les éléments non textuels comme les bordures de bouton, les contours de champs de formulaire et les icônes porteuses de sens. Un bouton avec un contraste de texte parfait de 7:1 peut quand même échouer à un audit si sa bordure se fond dans l’arrière-plan.
Vérifier le contraste sur le mauvais arrière-plan. Un texte posé sur une photo, un dégradé ou une superposition semi-transparente n’a pas une seule couleur de fond, il en a plusieurs. Le ratio ne vaut que pour le point précis mesuré ; un dégradé clair en haut et sombre en bas demande de vérifier le point le plus défavorable, pas la moyenne.
Supposer que les couleurs de marque sont exemptées. Le logotype lui-même échappe aux exigences de contraste, mais le texte courant et l’interface dans une couleur de marque n’y échappent pas. Beaucoup de bleus et de rouges de marque qui fonctionnent bien en accent de logo échouent au 4,5:1 une fois utilisés comme texte de paragraphe de 16px sur blanc.
Questions fréquentes
Quelle est la différence entre AA et AAA ? L’AA est le standard que citent la plupart des obligations légales d’accessibilité (ADA aux États-Unis, EN 301 549 dans l’UE), et c’est ce que vérifie la majorité des audits. L’AAA est plus strict et vise surtout un contenu pensé spécifiquement pour les utilisateurs malvoyants ; le WCAG précise lui-même que l’AAA n’est pas atteignable pour tous les types de contenu, donc la plupart des organisations ciblent l’AA partout plutôt que l’AAA systématiquement.
Le ratio de contraste tient-il compte du daltonisme ? Non. Le ratio de contraste mesure la luminance (la luminosité), pas la teinte, donc il aide accessoirement de nombreuses formes de daltonisme en ne reposant pas sur la capacité à distinguer des couleurs précises. Mais il ne remplace pas un test de daltonisme : deux couleurs peuvent avoir un excellent contraste tout en restant difficiles à différencier pour une personne daltonienne rouge-vert si elles se distinguent surtout par la teinte plutôt que par la clarté.
Pourquoi le noir pur sur blanc donne-t-il exactement 21:1 et pas un chiffre plus rond ?
La luminance du noir est 0 et celle du blanc est 1. En les injectant dans la formule du ratio, on obtient (1 + 0,05) / (0 + 0,05) = 1,05 / 0,05 = 21. Le résultat tombe exactement sur 21:1 à cause du choix de la constante +0,05, ni par hasard ni par arrondi.
Un thème sombre nécessite-t-il des vérifications de contraste séparées ? Oui. Remplacer un fond clair par un fond sombre ne conserve pas le ratio : du texte blanc sur le bleu de votre marque et du texte bleu de marque sur un fond presque noir forment deux paires de luminance différentes, avec deux ratios différents, donc chaque thème doit repasser par le vérificateur plutôt que de supposer que le résultat du mode clair reste valable.