English

Les couleurs mentent

Table des matières

La bordure qui ne change pas

Tu codes un formulaire. Le champ email est required, le label est en place, la validation HTML native fait son travail. Quand l'utilisateur oublie de remplir le champ, la bordure passe en rouge. Exactement comme sur la maquette. Tu testes, ça marche, le designer valide, tu passes à la suite.

Sauf que pour 1 homme sur 12, cette bordure n'a pas changé de couleur. Le rouge et le gris, c'est la même chose. Le champ est invalide, mais rien ne le dit. Et personne ne viendra se plaindre. 56% des utilisateurs mécontents ne disent rien, ils se tournent discrètement vers un concurrent.

Les couleurs mentent. Pas parce qu'elles sont fausses, mais parce qu'elles te donnent l'illusion que l'information passe, alors qu'elle s'arrête en chemin pour une partie de ton audience.

Cet article va te montrer à qui tes couleurs mentent, pourquoi le problème est plus répandu que tu ne le penses, et comment construire des interfaces qui disent la vérité à tout le monde.

Ce que tes yeux ne montrent pas aux leurs

Le daltonisme, ce n'est pas voir en noir et blanc. C'est un spectre de perceptions différentes, et il touche beaucoup plus de monde que tu ne le crois.

300 millions de personnes dans le monde ne perçoivent pas les couleurs correctement. 8% des hommes. 0,5% des femmes. Sur les 200 personnes qui visiteront ta page aujourd'hui, 8 ou 9 verront tes interfaces différemment de ce que tu as prévu.

Les formes les plus courantes, la protanopie et la deutéranopie, affectent la perception du rouge et du vert. 1 homme sur 12. Ce sont précisément les couleurs que l'industrie utilise partout pour signaler les erreurs et les succès. Le rouge "danger" et le vert "OK" sont invisibles à ceux qui en auraient le plus besoin.

Il y a une anecdote connue à ce sujet : Mark Zuckerberg a choisi le bleu pour Facebook parce que c'est la couleur qu'il perçoit le mieux, il est daltonien. Et il avait raison de s'adapter : le bleu est la couleur la plus résistante au daltonisme. Les formes qui affectent la perception du bleu (la tritanopie) touchent environ 1 personne sur 10 000, contre 1 homme sur 12 pour le rouge-vert.

Mais la vraie leçon de cette anecdote, ce n'est pas "utilise du bleu". C'est que la couleur est un canal de communication qui ne fonctionne pas de la même façon pour tout le monde. Et si elle ne fonctionne pas pour 8% de la population masculine, ce n'est pas un edge case, c'est une faille dans le design.

Le test que personne ne fait

Le rapport WebAIM Million 2026 a analysé 1 million de pages d'accueil. Le problème d'accessibilité numéro un, année après année : les contrastes insuffisants. 83,9% des pages sont concernées, avec en moyenne 34 erreurs de contraste par page.

Ce qui rend ce chiffre difficile à accepter, c'est que ces erreurs sont détectables automatiquement. Pas besoin d'un audit. Pas besoin d'un expert. Pas besoin d'un budget. WAVE, l'outil utilisé par WebAIM pour cette étude, est une extension navigateur gratuite. Tu l'installes, tu l'ouvres sur ta page, et les problèmes apparaissent directement sur les éléments concernés, avec le ratio mesuré et le minimum requis.

10 secondes. C'est le temps qu'il faut pour savoir si ta page ment sur ses couleurs.

Mais qu'est-ce qu'un ratio de contraste, exactement ? Ce n'est pas un chiffre arbitraire inventé par un comité. C'est une mesure de la différence de luminosité entre deux couleurs. Le texte et son fond. Plus le ratio est élevé, plus le texte reste lisible quand les conditions se dégradent.

Le RGAA impose un ratio minimum de 4,5:1 pour le texte standard. C'est le niveau AA, et c'est le plancher légal dans le cadre de l'EAA. Pour les textes larges (à partir de 24px, ou 18,66px en gras), le seuil descend à 3:1. Les caractères plus grands compensent naturellement un contraste plus faible.

Au-delà du RGAA, les WCAG définissent un niveau renforcé. AAA, à 7:1 pour le texte standard et 4,5:1 pour les textes larges. C'est ce que vise Bariafuri, et ce qui garantit une lisibilité confortable pour le plus grand nombre : écran en plein soleil, fatigue oculaire, moniteur vieillissant, ou simplement des yeux qui ne perçoivent pas toutes les nuances.

Un exemple concret : du texte gris #767676 sur fond blanc #FFFFFF donne un ratio de 4,54:1, tout juste AA. Ça passe le seuil, mais c'est inconfortable à lire sur un écran moyen. Monte à #595959 et tu atteins 7,00:1, AAA au seuil près. La différence est subtile à l'oeil, mais réelle à la lecture prolongée.

Tu peux vérifier tes combinaisons en quelques secondes avec le WebAIM Contrast Checker ou Tanaguru Contrast Finder. Ce dernier te suggère automatiquement une couleur alternative si ta combinaison échoue.

La couleur ne doit jamais être seule

Il y a un principe dans le RGAA qui résume tout ce que tu viens de voir. Les critères du thème "Couleurs" :

  • Critère 3.1 — ne pas utiliser la couleur comme seul moyen de transmettre une information
  • Critère 3.2 — contraste minimum du texte : 4,5:1 standard, 3:1 grands textes (niveau AA)
  • Critère 3.3 — contraste des composants d'interface et éléments graphiques : 3:1 (niveau AA)
  • WCAG 1.4.6 — Contraste renforcé — contraste du texte : 7:1 standard, 4,5:1 grands textes (niveau AAA, non couvert par le RGAA)

Pas "n'utilisez pas de couleur". Pas "les couleurs c'est mal". Juste : ne la laissez pas seule. Doublez chaque signal couleur d'un signal qui ne dépend pas de la perception des teintes.

Reprenons le formulaire de l'introduction. La bordure rouge ne suffit pas. Voici ce qui suffit :

form-validation.html
<form>
  <label for="email">Adresse email</label>
  <input
    id="email"
    type="email"
    required
    aria-describedby="email-error"
  />
  <p id="email-error" class="error-message" aria-live="polite">
    Ce champ attend une adresse email au format nom@domaine.fr
  </p>
</form>
form-validation.css
input:not(:user-invalid) + .error-message {
  display: none;
}
 
input:user-invalid {
  border-color: var(--color-error);
}
 
.error-message {
  color: var(--color-error);
  font-size: var(--font-size-sm);
}
 
.error-message::before {
  content: "⚠" / "";
  margin-inline-end: var(--space-1);
}

La couleur est toujours là. La bordure change pour ceux qui la perçoivent. Mais elle n'est plus seule. Le message textuel dit ce qui ne va pas. L'icône ⚠ en pseudo-élément CSS signale visuellement le problème sans dépendre de la couleur et sans polluer le HTML. Attention en revanche à l'arbre d'accessibilité : les lecteurs d'écran modernes lisent le contenu CSS généré, et le "⚠" serait annoncé "warning sign" en plein milieu du message. La syntaxe de texte alternatif content: "⚠" / "" le déclare décoratif : le texte du message suffit. Et :user-invalid, contrairement à :invalid, ne se déclenche qu'après l'interaction de l'utilisateur, pas au chargement de la page.

Une réserve sur l'annonce vocale : révéler un message pré-rempli en basculant son display est capricieux selon les lecteurs d'écran, la région live ne détecte pas toujours le changement. Le pattern robuste, l'injection du texte en JavaScript dans un conteneur déjà présent, est détaillé dans le laissez-passer A-38, partie 2.

Ce pattern couleur + texte + icône s'applique partout.

Les liens dans du texte

Un lien qui ne se distingue du texte que par sa couleur est invisible pour un daltonien. La solution la plus simple et la plus robuste :

links.css
a {
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: var(--underline-offset);
}

Le soulignement ne dépend d'aucune perception colorimétrique. C'est d'ailleurs pour ça qu'il existe depuis les débuts du web, et le retirer est presque toujours une erreur.

Les graphiques et visualisations

Un graphique en barres dont les séries ne se distinguent que par la couleur est illisible pour une partie de ton audience. Trois solutions complémentaires :

  • Des textures ou patterns en plus des couleurs (hachures, pointillés, remplissage plein)
  • Des labels directement sur les éléments, pas uniquement dans une légende séparée
  • Une légende textuelle qui ne repose pas sur la correspondance couleur ↔ signification

Les états d'interface

Bouton actif vs inactif, onglet sélectionné vs non sélectionné, élément activé vs désactivé. Si la seule différence est la couleur, le signal est perdu. Combine :

  • Couleur + bordure ou outline
  • Couleur + label textuel ("Actif", "Sélectionné")
  • Couleur + changement d'icône
  • Couleur + variation typographique (gras, style)

La règle est simple : si tu retires la couleur de ton interface et que l'information disparaît, c'est qu'elle était seule. Et si elle était seule, elle mentait à une partie de ton audience.

Quand l'utilisateur reprend le contrôle

Tout ce que tu as vu jusqu'ici suppose que tes couleurs arrivent jusqu'à l'utilisateur. Mais certains utilisateurs ne te laissent pas ce choix. Ils imposent les leurs.

Windows, macOS et Linux proposent des modes de contraste élevé. L'utilisateur choisit un thème avec une poignée de couleurs, parfois 8, parfois moins, et le navigateur remplace ta palette par la sienne. Automatiquement. Sans te demander ton avis.

Ce n'est pas un bug. C'est une fonctionnalité pensée pour des personnes qui ne peuvent tout simplement pas utiliser ta palette. Déficience visuelle sévère, photosensibilité, fatigue oculaire chronique. Pour elles, c'est ça ou ne pas utiliser le web.

Et quand ce mode s'active, des choses cassent dans ton CSS.

Les box-shadow disparaissent. Les gradients sont aplatis. Les bordures subtiles deviennent invisibles. Et les icônes SVG bicolores peuvent devenir un aplat uniforme quand toutes leurs couleurs sont remplacées par la même valeur système.

C'est là qu'intervient @media (forced-colors: active). Pas pour redéfinir toute ta palette, mais pour corriger ce qui casse :

forced-colors-fixes.css
/* Un bouton qui reposait sur un box-shadow
   pour se démarquer → ajouter une vraie bordure */
@media (forced-colors: active) {
  .btn {
    border: var(--border-width) solid ButtonText;
  }
}

ButtonText, Canvas, Highlight… le CSS propose une vingtaine de mots-clés système qui pointent vers les couleurs choisies par l'utilisateur. Tu ne décides plus quelles couleurs appliquer. Tu décides quels rôles tes éléments jouent, et le navigateur leur attribue la bonne couleur.

Pour les icônes SVG, la solution la plus simple :

svg-icons.css
.icon {
  fill: currentColor;
}

currentColor lie la couleur de l'icône à la couleur du texte environnant. En mode normal, elle suit ton design. En forced-colors, elle suit le thème de l'utilisateur. Un seul mot-clé, zéro maintenance.

Pour les SVG multi-couleurs, un logo, un schéma, c'est plus délicat. Deux options :

  • Remapper chaque élément du SVG sur des couleurs système distinctes (ButtonText, Highlight, LinkText)
  • En dernier recours, forced-color-adjust: none pour conserver les couleurs d'origine mais uniquement si tu as vérifié que le SVG reste lisible sur le nouveau fond
svg-multicolor.css
/* Dernier recours — conserver les couleurs d'origine */
.logo-multicolor {
  forced-color-adjust: none;
}

forced-color-adjust: none est un opt-out. Tu dis au navigateur : "je gère moi-même". C'est une responsabilité, pas un raccourci. Si tu l'utilises, tu testes.

La plupart des développeurs n'ont jamais activé le mode contraste élevé sur leur machine. Si c'est ton cas, je t'invite à le faire maintenant, ne serait-ce que 5 minutes, et à naviguer sur ton propre site. Ce que tu verras te surprendra probablement.

Construire un design qui ne ment pas

Les sections précédentes t'ont donné des corrections ponctuelles. Un aria-describedby ici, un forced-colors là. Mais corriger au cas par cas, c'est jouer à la taupe. Le vrai changement, c'est d'intégrer ces réflexes en amont, dans la façon dont tu conçois.

Commence en niveaux de gris

Avant d'appliquer ta palette, regarde ton interface sans couleur. Ouvre les DevTools de Chrome, onglet Rendering, et active la simulation "Achromatopsia". Si ton interface fonctionne en niveaux de gris, si les erreurs sont identifiables, les liens repérables, les états distinguables, alors la couleur que tu ajouteras ensuite sera un bonus, pas une béquille.

Teste ce que tes utilisateurs voient

Les DevTools proposent plusieurs simulations de déficience visuelle : protanopie, deutéranopie, tritanopie, vision floue. Active-les sur ta page en cours de développement, pas en fin de projet. 30 secondes suffisent pour repérer un signal qui repose uniquement sur la couleur.

Et pour aller plus loin que la simulation, active le mode contraste élevé de ton OS et navigue sur ton propre site. C'est souvent là que tu découvres les box-shadow qui servaient de bordure, les SVG qui disparaissent, et les subtilités visuelles qui n'en étaient pas.

Intègre forced-colors dans ton design system

Ne traite pas forced-colors comme un patch que tu ajoutes à la fin. Ajoute-le dans ton fichier de base, à côté de tes media queries prefers-color-scheme et prefers-reduced-motion :

base-theme.css
/* Mode sombre via light-dark() — pas de media query nécessaire */
:root {
  color-scheme: light dark;
  --color-bg: light-dark(#F0FDFA, #0D1B19);
  --color-text: light-dark(#134E4A, #CCFBF1);
}
base-media-queries.css
/* Les 3 media queries d'adaptation utilisateur */
@media (prefers-reduced-motion: reduce) { /* … */ }
@media (prefers-contrast: more)         { /* … */ }
@media (forced-colors: active)          { /* … */ }

light-dark() remplace prefers-color-scheme pour les valeurs de couleur : le navigateur choisit la bonne valeur selon le thème actif. Pour tout le reste (images conditionnelles, ombres, logique de thème), la media query reste nécessaire. Les 3 autres media queries n'ont pas d'équivalent fonctionnel et restent nécessaires. Si ces lignes sont dans ton socle dès le premier jour, chaque composant que tu construis sera pensé pour y répondre.

Vérifie avec les bons outils

Pas besoin d'un audit pour commencer. Ces outils sont gratuits et donnent des résultats en quelques secondes :


Et pour conclure, un dernier rappel. Les couleurs ne sont pas l'ennemi. Elles sont un outil puissant, quand elles ne sont pas seules. Un rouge d'erreur accompagné d'un message, d'une icône et d'un attribut ARIA reste un rouge d'erreur efficace. Il dit simplement la vérité à tout le monde, pas seulement à ceux qui le perçoivent.

Construire un design qui ne ment pas, ce n'est pas renoncer aux couleurs. C'est arrêter de leur faire porter seules un message qu'elles ne peuvent pas garantir.

Les critères d'ensemble

  • RGAA 3.1 — l'information ne doit pas être donnée uniquement par la couleur
  • RGAA 3.2 — contraste minimum du texte : 4,5:1 standard, 3:1 grands textes
  • RGAA 3.3 — contraste des composants d'interface et éléments graphiques : 3:1
  • WCAG 1.4.6 — contraste renforcé : 7:1 standard, 4,5:1 grands textes (niveau AAA, non couvert par le RGAA)

Ces critères couvrent l'ensemble de ce que cet article décrit : ne jamais transmettre une information uniquement par la couleur, garantir un contraste suffisant pour le texte et les composants, et offrir un mode renforcé pour ceux qui en ont besoin.

Sources