English

Le contraste parfait n'existe pas

Table des matières

Tu as fait le travail, et ça ne suffit pas

Dans Les couleurs mentent, je montrais comment construire un design qui dit la vérité : doubler chaque signal couleur d'un signal textuel, vérifier les ratios de contraste, tester en forced-colors. Tu as peut-être appliqué tout ça. Tu vises AAA, 7:1 partout. Ton validateur est au vert.

Et pourtant, il reste des gens pour qui tes couleurs ne fonctionnent pas.

Prenons l'achromatopsie incomplète. Ces personnes gardent une vision résiduelle des couleurs, mais réduite, et surtout différente d'une personne à l'autre. Certaines distinguent encore une trace de rouge, d'autres un peu de bleu, selon les cônes qui fonctionnent encore. Il n'y a pas une achromatopsie, il y en a autant que de personnes concernées.

Pour elles, le ratio de contraste WCAG ne décrit pas leur réalité. La formule est calculée sur une vision typique, à trois cônes. Deux couleurs que la norme juge parfaitement contrastées peuvent leur apparaître identiques. Et l'inverse est vrai aussi : deux couleurs jugées proches peuvent leur sembler distinctes. Le ratio parfait sur le papier ne garantit rien dans leur perception.

On mesure, on valide, on coche la case. Et il reste des gens pour qui ça ne marche pas, parce qu'aucune mesure statistique ne peut couvrir une perception aussi singulière.

Alors on cherche la couleur magique ? Elle n'existe pas. La vraie réponse, ce n'est pas de mieux choisir. C'est de laisser choisir.

Qui tient le volant

Quand un utilisateur active le mode couleurs forcées, il définit ses propres couleurs : texte, fond, liens. Le navigateur les applique à ton site en contournant ton CSS. Tu le détectes avec forced-colors: active et tu restes cohérent grâce aux mots-clés système comme Canvas ou CanvasText.

La question, c'est : qui fournit ce mécanisme ?

EnvironnementQui tient le volantMedia query
Windows — Edge, Chrome, FirefoxL'OS impose les couleursforced-colors: active
macOS — FirefoxLe navigateur propose le mode (réglage « Couleurs »)forced-colors: active
macOS — Safari, Chrome, EdgePersonne ne force les couleursprefers-contrast: more
Linux — Firefox, ChromiumL'OS (thème à contraste élevé) ou Firefoxforced-colors: active
Android — Chrome, Edge, FirefoxPersonne ne force les couleursaucun levier fiable
iOS — SafariPersonne ne force les couleursprefers-contrast: more
iOS — Chrome, Firefox, EdgePersonne ne force (moteur WebKit imposé)prefers-contrast: more

La ligne de partage n'est pas Windows contre macOS. C'est : qui tient le volant. Sur Windows, l'OS. Sur macOS et Linux avec Firefox, le navigateur. Partout ailleurs, Chrome, Edge, Safari et tout l'écosystème mobile, personne ne force quoi que ce soit.

La dernière ligne du tableau mérite qu'on s'y arrête. Chrome sur iPhone, Firefox sur iPad : ce sont des surcouches autour du moteur WebKit d'Apple. Quelle que soit l'icône sur l'écran d'accueil, c'est Safari qui fait le rendu. Et Safari, l'équipe WebKit le documente noir sur blanc :

La valeur custom de prefers-contrast ne retourne pas "true" sur les plateformes Apple, puisqu'il n'existe aucun mode couleurs forcées dans iOS, iPadOS, macOS ou visionOS.

Chez Safari, une media query non satisfaite s'évalue simplement à faux : forced-colors: active ne sera jamais vraie. Il n'y a rien à activer.

La réglementation européenne (DMA) autorise les moteurs alternatifs sur iOS dans l'Union européenne depuis iOS 17.4. Mais à ce jour, aucun navigateur n'a publié de version utilisant un moteur non-WebKit. La situation du tableau reste donc exacte.

Sur Safari, tout ce que tu reçois, c'est prefers-contrast: more. Pas une palette, juste une intention : "je veux plus de contraste". Et c'est à toi d'y répondre.

Ne pas gêner

Ton rôle n'est pas de choisir le bon contraste. C'est de ne pas empêcher l'utilisateur de choisir le sien.

Pour forced-colors: active

C'est le cas couvert dans Les couleurs mentent. Quand le mode couleurs forcées est actif, le navigateur remplace ta palette. Ton travail, c'est de vérifier que rien d'essentiel ne repose sur ce qu'il ne sait pas remplacer tout seul : une information portée par une background-image, une ombre, une bordure que tu croyais décorative.

Active le mode contraste élevé sur ta machine. Navigue sur ton propre site. Ce que tu verras te surprendra probablement.

Pour prefers-contrast: more

C'est le filet de sécurité pour Safari et pour tout l'écosystème mobile Apple. L'utilisateur ne redéfinit pas tes couleurs, il te dit qu'il en a besoin de meilleures. C'est à toi de répondre, dans ton propre design :

prefers-contrast.css
@media (prefers-contrast: more) {
  :root {
    --color-border: var(--color-text);
    --color-bg-subtle: var(--color-bg);
  }
 
  .btn-secondary {
    border-width: 2px;
  }
}

Épaissir les bordures, supprimer les fonds subtils qui brouillent la lisibilité, renforcer les séparations visuelles. Pas une refonte, quelques ajustements ciblés qui font la différence pour ceux qui les ont demandés.

Les deux ensemble

Les deux media queries ne s'excluent pas. Elles couvrent des cas différents, et parfois les mêmes : quand Firefox force les couleurs, il positionne aussi prefers-color-scheme et prefers-contrast en fonction du thème choisi, et sur Windows les deux sont actives en même temps. Intègre-les dans ton socle CSS aux côtés de tes autres media queries d'adaptation :

adaptation-utilisateur.css
@media (prefers-reduced-motion: no-preference) { /* animations */ }
@media (prefers-contrast: more)                 { /* … */ }
@media (forced-colors: active)                  { /* … */ }

Si ces lignes sont dans ton socle dès le premier jour, chaque composant que tu construis sera pensé pour y répondre.


Le meilleur contraste, c'est celui qu'on ne décide pas à sa place.

Sources