Design avec l’IA — du prompt au produit — 7. Couleur avancée : palettes, mode sombre et accessibilité totale

21 min read min de lecture
Chapitre 07

Couleur avancée : palettes, mode sombre et accessibilité totale

Chapitre 7 sur 10 · 70%

Objectifs de ce chapitre

  • Étendre la palette en échelles de teintes cohérentes
  • Construire un mode sombre qui n’est pas un simple négatif
  • Garantir l’accessibilité au-delà du texte : daltonisme, non-texte, états

Quand une palette rencontre le monde réel

Deux retours tombent le même matin chez Studio Mango. Le premier vient d'un bêta-testeur de Sereno : « Je suis daltonien, et je ne vois pas la différence entre vos messages de succès et d'erreur. » Le second vient du client : « Mes utilisateurs méditent le soir — il nous faut un mode sombre. » Deux demandes différentes, une même leçon : la palette du chapitre 2, parfaite en conditions idéales, doit maintenant affronter la diversité réelle des yeux et des contextes d'usage.

Ce chapitre complète ta boîte à outils couleur sur quatre fronts : étendre chaque couleur en échelle de teintes (parce que huit couleurs ne suffisent jamais longtemps), raisonner en luminosité perçue avec OKLCH, construire un mode sombre digne de ce nom, et pousser l'accessibilité au-delà du contraste du texte — daltonisme, éléments non textuels, états sémantiques. À la fin, tu ne livreras plus une palette : tu livreras un thème complet.

Des couleurs aux échelles de teintes

Ton token --color-primary est une teinte unique. Mais dès que l'interface grandit, tu as besoin de ses voisines : une version très claire pour un fond de bandeau, une version foncée pour le survol, une version presque noire pour du texte sur fond clair. Plutôt que d'improviser ces variantes au cas par cas, les design systems professionnels définissent une échelle de 9 à 11 nuances par teinte, numérotées de 50 (la plus claire) à 900 (la plus foncée).

Chaque numéro a un rôle conventionnel : 50-100 pour les fonds teintés subtils, 200-300 pour les bordures et états désactivés, 500 comme couleur de base, 600-700 pour les survols et états actifs, 800-900 pour du texte de la teinte sur fond clair. Cette convention rend les décisions rapides et cohérentes : « le bandeau d'information utilise sage-50 en fond et sage-800 en texte » se comprend immédiatement, et le contraste est presque garanti par construction — les extrêmes d'une échelle bien faite passent AA entre eux.

css
:root {
  /* Échelle sage — générée à luminosité perçue régulière */
  --sage-50:  #F2F6F4;   /* fonds teintés subtils */
  --sage-100: #E1EAE6;
  --sage-200: #C4D5CE;   /* bordures, séparateurs */
  --sage-300: #A3BDB3;
  --sage-400: #7E9D91;
  --sage-500: #4A7C6F;   /* base : boutons, liens */
  --sage-600: #3D685D;   /* survol */
  --sage-700: #32554C;   /* actif */
  --sage-800: #27423B;   /* texte teinté sur fond clair */
  --sage-900: #1C302B;
}

/* Les rôles pointent vers l'échelle — jamais l'inverse */
:root {
  --color-primary: var(--sage-500);
  --color-primary-hover: var(--sage-600);
  --color-primary-surface: var(--sage-50);
}

Note l'architecture à deux étages du code ci-dessus : l'échelle brute (--sage-500) d'un côté, les rôles fonctionnels (--color-primary) de l'autre, les rôles pointant vers l'échelle. Cette indirection est la clé du mode sombre qui arrive plus bas : tu changeras ce que les rôles désignent, sans toucher ni à l'échelle ni aux composants.

OKLCH : raisonner en luminosité perçue

Pour générer ces échelles, le format de couleur compte plus qu'on ne croit. Le HSL classique a un défaut connu : sa « luminosité » ment. Un jaune et un bleu à 50 % de luminosité HSL n'ont pas du tout la même clarté perçue par l'œil — le jaune paraît éclatant, le bleu sombre. Conséquence : une échelle générée en HSL a des marches irrégulières, et les ratios de contraste deviennent imprévisibles d'une teinte à l'autre.

Le format moderne OKLCH corrige cela : son axe L mesure la luminosité telle que l'œil la perçoit. Deux couleurs OKLCH de même L paraissent réellement aussi claires l'une que l'autre, quelle que soit la teinte. Pour toi, c'est un superpouvoir pratique : demande tes échelles « en OKLCH, avec un pas de luminosité régulier », et toutes tes teintes (sage, pêche, rouge d'erreur) auront des nuances alignées — le 600 du vert et le 600 du rouge offriront le même contraste sur fond blanc.

OKLCH est supporté par tous les navigateurs modernes. Pour les très vieux navigateurs, demande à l'IA de fournir le fallback hexadécimal de chaque valeur — deux lignes par token, la version hex d'abord, la version oklch ensuite.
PROMPT
Étends mon design system Sereno en échelles de teintes complètes :
- pour chaque couleur de base (sage #4A7C6F, pêche #E8A87C, rouge erreur #B5544D), génère une échelle de 10 nuances (50 à 900) en OKLCH avec un pas de luminosité perçue régulier
- garde la teinte et ajuste surtout luminosité et chroma : les nuances claires légèrement désaturées, les foncées légèrement plus saturées
- donne pour chaque nuance : la valeur oklch(), le fallback hex, et le ratio de contraste sur blanc ET sur #1A1F1D
- termine par un tableau des combinaisons garanties AA : quel numéro de texte sur quel numéro de fond
Format : bloc :root CSS commenté.

Le mode sombre n’est pas un négatif

Première intuition à tuer : le mode sombre n'est pas l'inversion de la palette claire. Inverser produit un fond noir pur (#000) qui fait vibrer le texte blanc, des couleurs saturées qui deviennent fluorescentes, et des ombres invisibles. Un bon thème sombre repose sur quatre principes. Un : un fond gris très foncé teinté (pour Sereno, un gris-vert profond comme #141816), jamais du noir pur. Deux : des couleurs désaturées — sur fond sombre, la même saturation paraît plus criarde, donc on descend la chroma d'un cran.

Trois : l'élévation par la clarté. En mode clair, une carte se détache par son ombre ; en mode sombre, les ombres ne se voient plus — c'est la surface elle-même qui s'éclaircit légèrement (une carte est un peu plus claire que le fond, une modale encore un peu plus). Quatre : le texte blanc cassé plutôt que blanc pur (#E8ECEA plutôt que #FFFFFF), pour réduire la vibration sur les longues lectures nocturnes — précisément le contexte d'usage de Sereno.

Et c'est ici que ton architecture à deux étages paie : pour créer le thème sombre, tu ne touches ni aux composants ni à l'échelle — tu re-déclares uniquement les rôles dans un bloc prefers-color-scheme: dark. --color-surface pointe désormais vers le gris profond, --color-primary vers un sage-400 plus clair (car sur fond sombre, c'est la version claire de la teinte qui contraste). Trente lignes de CSS, et toute l'interface bascule.

css
/* Mode sombre : on re-déclare les rôles, rien d'autre */
@media (prefers-color-scheme: dark) {
  :root {
    --color-surface: #141816;          /* gris-vert profond, pas de noir pur */
    --color-surface-raised: #1E2421;   /* élévation par la clarté */
    --color-text: #E8ECEA;             /* blanc cassé, pas de blanc pur */
    --color-text-muted: #9DABA5;       /* re-vérifié : 5.2:1 sur surface */
    --color-primary: var(--sage-400);  /* version claire de la teinte */
    --color-primary-hover: var(--sage-300);
    --color-primary-surface: #20302B;
    --shadow-soft: none;               /* l'élévation remplace l'ombre */
    --shadow-raised: none;
  }
}
PROMPT
Génère le thème sombre complet de Sereno à partir de mes tokens clairs (ci-dessous) :
[colle ici ton bloc :root + tes échelles]
Règles :
- re-déclare UNIQUEMENT les rôles dans @media (prefers-color-scheme: dark), sans toucher aux échelles ni aux composants
- fond gris-vert profond (pas de noir pur), texte blanc cassé (pas de #FFF)
- désature légèrement les accents, utilise les nuances claires des échelles pour primary
- remplace les ombres par l'élévation : surface-raised plus claire que surface
- donne le ratio de contraste de CHAQUE combinaison texte/fond du thème sombre
- signale toute combinaison sous 4,5:1 et propose la correction
Le mode sombre remet tous les compteurs de contraste à zéro : une combinaison AA en clair peut échouer en sombre. Le piège classique est --color-text-muted, déjà limite en clair, qui devient illisible sur fond sombre. Exige les ratios chiffrés des deux thèmes.

Daltonisme : ne jamais coder l’information par la couleur seule

Revenons au bêta-testeur. Environ 8 % des hommes et 0,5 % des femmes perçoivent mal certaines couleurs — le plus souvent la distinction rouge/vert, exactement la paire que Sereno utilise pour erreur/succès. La règle d'accessibilité est absolue : la couleur ne doit jamais être le seul canal qui porte une information. Un message d'erreur rouge doit aussi être signalé par une icône, un préfixe textuel (« Erreur : »), ou une forme distincte. Un champ invalide doit avoir une bordure plus épaisse ou une icône, pas seulement une bordure rouge.

Le réflexe de vérification : demande à l'IA de simuler. « Décris cette interface telle que la verrait une personne deutéranope ; liste chaque endroit où une information n'est portée que par la couleur. » Tu peux aussi faire le test mental du niveau de gris : si toute la page passait en noir et blanc, les états resteraient-ils distinguables ? Si oui, ton design est robuste ; si non, tu sais quoi doubler par une icône ou un libellé.

WCAG au-delà du texte : le 3:1 des éléments d’interface

Le chapitre 2 a couvert le texte (4,5:1). Mais les WCAG imposent aussi un minimum de 3:1 pour les éléments non textuels porteurs de sens : la bordure d'un champ de formulaire (sinon le champ est invisible), une icône qui sert de bouton, l'anneau de focus, l'état coché d'une case, le tracé d'un graphique. C'est l'angle mort de presque toutes les palettes pastel — la bordure gris clair si élégante de ta maquette fait probablement 1,8:1, et un utilisateur malvoyant ne trouve simplement pas où cliquer.

Pense aussi aux états sémantiques comme à des couples complets : chaque couleur de statut (succès, erreur, avertissement, information) existe en version texte, version fond et version bordure — et chaque combinaison passe ses seuils dans les deux thèmes. C'est le moment où ton système quitte la « jolie palette » pour devenir un véritable thème de production.

flowchart TD
  P["Palette de base : rôles et teintes"] --> E["Échelles 50 à 900 en OKLCH"]
  E --> T1["Ratios texte : 4,5 pour 1 minimum"]
  E --> T2["Ratios non-texte : 3 pour 1 minimum"]
  T1 --> D["Simulation daltonisme : info jamais par couleur seule"]
  T2 --> D
  D --> S["Thème sombre : rôles re-déclarés et re-testés"]
  S --> V["Thème validé : light + dark documentés"]
Le pipeline de validation couleur : de la palette au thème complet, chaque étape a son test.

Livrer un thème, pas des couleurs

Récapitulons le livrable final pour le développeur de Sereno : les échelles de teintes (la matière première), les rôles fonctionnels en deux déclarations (clair et sombre), les couples d'états sémantiques complets, et un court document d'usage — quel numéro d'échelle pour quel usage, quelles combinaisons sont garanties, comment ajouter une teinte sans casser le système. Ajoute le respect du choix utilisateur : le thème suit prefers-color-scheme par défaut, mais un interrupteur manuel doit pouvoir le forcer, car méditer le soir en mode clair forcé n'est pas une expérience premium.

Le bêta-testeur daltonien recevra une interface dont chaque état est doublé d'une icône ; le client aura son mode sombre digne d'une app de méditation nocturne. Et toi, tu as appris la leçon qui dépasse la couleur : un design system ne se juge pas en conditions idéales, mais sur la diversité réelle des yeux, des écrans et des contextes qui vont le rencontrer.

🛠️ À toi de jouer

Contexte

Le client attend le mode sombre pour la prochaine release, et le retour du bêta-testeur daltonien doit être traité dans la même passe. Tu disposes de tes tokens du chapitre 2 et d'une demi-journée. Le livrable : un thème clair + sombre complet, vérifié au-delà du texte, avec sa documentation d'usage pour le développeur.

Consignes

  1. Fais générer les échelles de 10 nuances (50-900) en OKLCH pour tes trois teintes principales, avec fallbacks hex et ratios de contraste.
  2. Restructure tes tokens en deux étages : échelles brutes d’un côté, rôles fonctionnels de l’autre.
  3. Génère le thème sombre en re-déclarant uniquement les rôles : fond teinté profond, accents désaturés, élévation par la clarté.
  4. Exige les ratios chiffrés de toutes les combinaisons des deux thèmes et fais corriger tout ce qui passe sous 4,5:1 (texte) ou 3:1 (non-texte).
  5. Fais l’audit daltonisme : demande la liste des informations portées uniquement par la couleur, et double chacune par une icône ou un libellé.
  6. Teste la landing complète dans les deux thèmes (y compris le formulaire et ses états d’erreur) et rédige les 10 lignes de documentation d’usage.
Indice — Commence par l'architecture à deux étages (échelles → rôles) : c'est elle qui rend le mode sombre quasi gratuit. Si tu dois modifier un composant pour le thème sombre, c'est le signe qu'une valeur en dur a échappé aux rôles.

En résumé

  • Une couleur de base devient une échelle de 9-11 nuances (50-900), chaque numéro ayant un rôle conventionnel.
  • L’architecture à deux étages — échelles brutes, rôles fonctionnels qui pointent dessus — rend les thèmes interchangeables.
  • OKLCH mesure la luminosité perçue : des échelles régulières et des contrastes prévisibles d’une teinte à l’autre.
  • Le mode sombre n’est pas un négatif : fond teinté profond, accents désaturés, élévation par la clarté, blanc cassé.
  • Tous les contrastes doivent être re-testés en sombre — le texte atténué est le piège classique.
  • L’information ne doit jamais être portée par la couleur seule : icône, libellé ou forme en double canal (8 % des hommes sont daltoniens).
  • Les WCAG imposent aussi 3:1 aux éléments non textuels : bordures de champs, icônes actives, focus, états.

Quiz — vérifie ta compréhension

1. À quoi sert une échelle de teintes (50 à 900) ?

Chaque numéro a un rôle conventionnel (50 = fond subtil, 500 = base, 600 = survol, 800 = texte teinté) : les décisions deviennent rapides et le contraste prévisible.

2. Quel est l’avantage d’OKLCH sur HSL ?

En HSL, un jaune et un bleu à « 50 % » n'ont pas la même clarté perçue. L'axe L d'OKLCH est perceptuel : même L = même clarté ressentie, donc des contrastes alignés entre teintes.

3. Comment construire un bon mode sombre ?

L'inversion produit des couleurs fluorescentes et des ombres invisibles. On re-déclare uniquement les rôles : gris teinté profond, blanc cassé, nuances claires des échelles pour les accents.

4. Que faire pour un utilisateur daltonien qui confond les messages d’erreur et de succès ?

La couleur ne doit jamais être le seul canal d'une information. Le test mental : en noir et blanc, les états doivent rester distinguables.

5. Quel ratio de contraste minimum s’applique aux éléments non textuels porteurs de sens (bordures de champs, icônes actives) ?

Les WCAG exigent 3:1 pour les composants d'interface : une bordure de champ à 1,8:1 rend le formulaire introuvable pour un utilisateur malvoyant.

6. Pourquoi re-tester tous les contrastes après création du thème sombre ?

Chaque rôle pointe vers de nouvelles valeurs : les ratios sont entièrement recalculés. Le texte atténué, déjà limite en clair, est le premier à tomber sous le seuil.

Auteur(s)

R

REHOUMA Haythem

Haythem Rehouma est un ingénieur et architecte IA et cloud, formateur et enseignant technique, avec un profil orienté IA médicale, AWS, MLOps, LLM/RAG et vision par ordinateur.