Théorie des couleurs pour les interfaces
La couleur dans l'UI est principalement un problème de luminosité déguisé en teinte. La hiérarchie, le contraste, la lisibilité et le mode sombre sont tous décidés par la luminosité ; la teinte porte l'identité et la signification ; le chroma (saturation) porte l'emphase. Travaillez dans cet ordre.
La boîte à outils — utilisez-la plutôt que de deviner
scripts/palette.py (Python 3, sans dépendances) calcule tout en OKLCH et mappe les couleurs dans le gamut sRGB. Ne devinez jamais un ratio de contraste ou n'inventez pas une rampe à la main quand vous pouvez la calculer.
S=<skill-dir>/scripts/palette.py # <skill-dir> = le répertoire de base affiché lorsque cette compétence se charge
python3 $S system "#6d28d9" # système complet : rampes + rôles clair/foncé, toutes les paires vérifiées
python3 $S system "#6d28d9" --format tailwind # Tailwind v4 @theme + variables sémantiques (aussi : css, json = DTCG)
python3 $S ramp "#0f766e" --format css # une rampe 50–950 (l'entrée est ramenée à son étape la plus proche)
python3 $S neutral "#0f766e" --tint 0.01 # rampe grise teintée vers la teinte de la marque
python3 $S contrast "#fff" "#7c3aed" # ratio WCAG + niveaux + APCA Lc
python3 $S cvd "#16a34a" "#dc2626" "#2563eb" # simulation daltonisme + paires confondantes
python3 $S harmony "#6d28d9" --scheme split # relations de teinte en OKLCH
python3 $S convert "hsl(...)/#hex/oklch(...)" # conversion de notation + à quel point la couleur est vive
system parcourt automatiquement les étapes d'une rampe lorsqu'une paire échoue (par exemple, il assombrit text-muted jusqu'à atteindre 4.5:1) et imprime chaque ajustement — transmettez-les à l'utilisateur, ce sont des décisions de conception.
Flux de travail : de « J'ai besoin de couleurs » aux tokens livrés
- Trouvez l'ancre. Une couleur de marque existante ? Utilisez-la. Aucune ? Dérivez-la de la personnalité du produit (voir Choisir une teinte ci-dessous) et proposez 2–3 graines avec une justification d'une ligne chacune, plutôt qu'une seule sélection arbitraire.
- Générez le système avec
palette.py system <graine>. Une rampe d'accent, une rampe neutre, et seulement les rampes d'état que le produit doit restituer. - Mappez les rôles sémantiques, n'utilisez jamais de primitives dans les composants (
--color-accent,--color-text-muted, pas--violet-600). La compétence de construction de système de design couvre l'architecture des tokens en profondeur. - Vérifiez : le contraste sur la paire rendue (texte sur son fond réel, y compris alpha/overlays), les deux thèmes, vérification CVD pour toute signification codée par couleur (graphiques, état, tags).
- Appliquez avec retenue (ci-dessous), puis regardez le rendu.
Quelle quantité de couleur : distribution
- Les neutres font ~90% du travail. Arrière-plans, surfaces, texte, bordures. Une UI construite sur de bons neutres avec un seul accent a presque toujours l'air plus professionnelle qu'une UI multiteinte.
- 60-30-10 est un bon indicateur : ~60% de neutre dominant, ~30% de surface secondaire/variation neutre, ~10% d'accent. Si l'accent dépasse ~10–15% des pixels, il cesse de signifier « agissez ici ».
- Une seule action primaire remplie par vue. La couleur sur le fond d'un bouton se lit comme primaire de loin ; le texte coloré se lit comme un lien.
- Une couleur, une signification. Si le violet signifie « marque/interactif », ne l'utilisez pas aussi pour un tag de catégorie. Les teintes d'état doivent être clairement séparées de l'accent (l'outil maintient ≥25° en teinte OKLCH).
- La couleur n'est jamais le seul signal. ~8% des hommes et ~0.5% des femmes ont une déficience de la vision des couleurs ; associez la couleur à une icône, un libellé, un motif ou une position.
Choisir une teinte (quand il n'y a pas de marque)
Les associations sont culture-dépendantes et faibles par rapport à l'exécution — une palette bien construite dans n'importe quelle teinte bat une teinte « psychologiquement correcte » mal utilisée. Utilisez-les comme départageurs :
| Famille de teintes | Lecture UI courante | Produits typiques | Attention |
|---|---|---|---|
| Bleu / indigo | confiance, calme, compétence | fintech, SaaS, santé, entreprise | le choix le plus générique ; poussez le chroma ou déplacez-vous vers l'indigo/cyan pour vous démarquer |
| Violet | créatif, premium, « IA » | outils créatifs, produits IA | le violet très saturé est maintenant un signe de « mélasse IA » |
| Vert / sarcelle | croissance, argent, santé, succès | finance, durabilité, bien-être | conflit avec le statut « succès » — ajustez la teinte d'état |
| Rouge / rose | énergie, urgence, passion | alimentaire, médias, divertissement | conflit avec « danger » ; utilisez pour les moments de marque, gardez les actions destructrices distinctes |
| Orange / ambre | chaleur, convivialité, action | grand public, alimentaire, places de marché | les oranges foncés virent au marron ; vérifiez les remplissages en mode clair |
| Jaune / citron vert | optimisme, attention | grand public, ludique | ne peut pas porter de texte blanc ; utilisez du texte foncé sur des remplissages jaunes, ou utilisez la marque comme accent-subtle et choisissez une étape plus foncée pour les remplissages (--hue-shift -15 garde les nuances dorées plutôt qu'olive) |
| Presque neutre (noir/pierre/sable) | luxe, éditorial, outillage | outils de dev, mode, portfolios | nécessite un savoir-faire typographique et spatial pour ne pas sembler vide |
Notes régionales à connaître : le rouge est chanceux/festif en Chine mais signifie perte dans la finance occidentale (et gain dans les tickers boursiers chinois/japonais) ; le blanc est associé au deuil dans certaines régions d'Asie de l'Est. Pour les UI financières, rendez les couleurs hausse/baisse configurables.
Couleur perceptuelle — pourquoi OKLCH
La luminosité HSL ment : hsl(60 100% 50%) (jaune) et hsl(240 100% 50%) (bleu) partagent « L=50% » mais diffèrent énormément en luminosité perçue. C'est pourquoi les rampes HSL ont un contraste inégal et des étapes sombres/clair qui ne s'alignent pas entre les teintes.
OKLCH = L (luminosité perçue 0–1) · C (chroma, ~0–0.37) · H (angle de teinte). L égal ≈ luminosité perçue égale entre les teintes, donc :
- la même étape entre les rampes (tous les
-600) a un contraste similaire contre le blanc, - vous pouvez faire pivoter la teinte sans changer la luminosité (harmonies, couleurs d'état qui « correspondent »),
- le mode sombre peut être dérivé en raisonnant sur L.
Inconvénients : le gamut sRGB est irrégulier — chaque teinte a un chroma maximum différent à chaque L (le jaune culmine près de L≈0.95, le bleu près de L≈0.45). L'outil mappe le gamut en réduisant le chroma, en gardant L et H. Les couleurs à large gamut (Display-P3) sont une amélioration : déclarez d'abord la valeur sRGB, puis la valeur vive P3/oklch() dans @media (color-gamut: p3).
CSS supporte oklch() dans tous les navigateurs modernes ; utilisez-le dans les nouveaux projets web. Sur les plateformes natives, convertissez dans la notation de la plateforme (hex/sRGB, Color(red:green:blue:), Color(0xFF…)) — l'option --notation hex de l'outil vous aide.
Rampes, neutres et teintes
- Les rampes contiennent une seule teinte d'un bout à l'autre, les étapes sont plus fines à l'extrémité claire (c'est là que vivent les arrière-plans et où l'œil est le plus sensible), et le chroma culmine au milieu de la rampe. 11 étapes (50–950, convention Tailwind) ou 12 (convention Radix, chaque étape a un travail nommé) — voir
references/ramps-and-roles.mdpour la carte des rôles. - Neutres teintés : mélangez un peu de la teinte de la marque dans les gris (chroma ≈ 0.005–0.02). Cela rend toute l'UI cohérente ; les gris #808080 purs semblent morts à côté d'un accent saturé. Marque chaude → gris chauds ; froide → froids.
- Jamais de noir pur sur blanc pur pour du texte long dans les UI de marque ; le quasi-noir (neutral-950) sur quasi-blanc réduit l'éblouissement. Les arrière-plans noirs purs en mode sombre provoquent des traînées sur OLED pendant le défilement ; utilisez L ≈ 0.13–0.18.
Le mode sombre n'est pas une inversion
- L'élévation va plus claire, pas plus ombre : surface > arrière-plan d'environ 0.03–0.06 L.
- Désaturez légèrement les accents et augmentez leur luminosité ; les tons moyens saturés vibrent sur les arrière-plans sombres.
- Le texte du corps est légèrement cassé (neutral-50/100), le texte atténué autour de neutral-400.
- Les remplissages inversent souvent leur libellé en texte sombre (l'outil décide en fonction du contraste).
- Re-mesurez chaque paire ; le contraste ne survit pas à un retournement. Voir
references/dark-mode.md.
Contraste — les normes
| Paire | WCAG 2.2 AA | AAA | Directive APCA (consultative) |
|---|---|---|---|
| Texte du corps (<24px / <18.66px gras) | 4.5:1 | 7:1 | Lc 75+ (90 préféré) |
| Texte large (≥24px ou ≥18.66px gras) | 3:1 | 4.5:1 | Lc 60+ |
| Composants UI & objets graphiques nécessaires à leur compréhension (bordures d'entrée, icônes, anneaux de focus, marques de graphique) | 3:1 (SC 1.4.11) | — | Lc 45+ |
| Contrôles désactivés, éléments décoratifs, logos | exempt | — | — |
WCAG 2.x est la base légale/conformité (ADA, EN 301 549 / European Accessibility Act). APCA (le candidat WCAG 3) modélise mieux la perception, en particulier pour le mode sombre et le texte clair, mais WCAG 3 n'est pas final — respectez WCAG 2.2 AA et utilisez APCA comme deuxième avis. Détails, règles des anneaux de focus et pièges dans references/contrast-and-cvd.md.
Dégradés, superpositions et alpha
- Interpolez les dégradés
in oklab(lisse, pas de milieu boueux) ; utilisezin oklchpour les balayages multi-teintes qui deviendraient gris au milieu. Gardez les points d'arrêt proches en luminosité pour les arrière-plans derrière le texte. - Texte sur images : un voile (superposition en dégradé) ou un support solide ; mesurez la pire zone.
- Les couleurs alpha (
/50,rgba) changent le contraste en fonction de ce qui se trouve en dessous. Préférez les tokens solides pour le texte ; réservez l'alpha pour les superpositions, les survols et les ombres.
Visualisation de données
Les palettes catégorielles ont besoin d'une luminosité à peu près égale et d'une séparation de teinte maximale ; les palettes séquentielles varient la luminosité de manière monotone ; les palettes divergentes partagent un point médian neutre. Utilisez la compétence dataviz si disponible — elle a une méthode de palette validée. Exécutez toujours palette.py cvd sur les couleurs des séries de graphiques.
Revoir les couleurs de quelqu'un — liste de contrôle rapide
- Chaque paire texte/arrière-plan mesurée dans les deux thèmes (pas estimée)
- Bordures d'entrée, anneaux de focus, icônes qui véhiculent une signification ≥ 3:1
- Pas de hex/rgb brut dans les composants ; seulement des tokens sémantiques
- Un seul accent, utilisé uniquement pour la signification interactive/principale
- Couleurs d'état distinctes de l'accent et les unes des autres sous simulation CVD
- Neutres teintés de manière cohérente (pas un mélange de gris froids et chauds)
- Mode sombre conçu (surfaces plus claires pour l'élévation, accents ajustés), pas inversé
- La signification n'est jamais portée par la couleur seule
Pour un audit complet du système de couleurs avec des résultats classés par gravité, la compétence better-colors est excellente ; pour choisir/dériver/générer, restez ici.
Références
references/ramps-and-roles.md— cartographie des rôles étape par étape (Tailwind 50–950 et Radix 1–12), couleurs d'état (survol/actif/désactivé/sélectionné)references/dark-mode.md— construction du thème sombre, élévation, spécificités de plateforme (couleurs sémantiques iOS, surfaces tonales Material)references/contrast-and-cvd.md— détails WCAG 2.2, niveaux APCA, indicateurs de focus, règles de conception CVDreferences/harmony-and-brand.md— schémas d'harmonie, dérivation des couleurs secondaires, traduction marque-UI, température, contraste simultané