frontend / css
Fonctions de couleur avancées : relative color, lab/lch, gamut
Explication
Ce que vous allez apprendre
- Comprendre pourquoi
oklchest "perceptuellement uniforme" contrairement àhsl - Dériver une couleur à partir d'une autre directement en CSS avec la relative color syntax
- Générer une palette de nuances (100 à 700) à partir d'une seule teinte de base
- Utiliser des espaces colorimétriques étendus (
lab,display-p3) pour des écrans compatibles - Comprendre ce que fait le navigateur quand une couleur dépasse le gamut de l'écran
Dans quel contexte ?
Une équipe design doit générer automatiquement les variantes :hover et :disabled de chaque couleur de sa charte, ainsi qu'une palette de 5 nuances (très clair à très foncé) pour chaque couleur de marque, sans dupliquer manuellement des dizaines de valeurs hexadécimales. La relative color syntax et color-mix() en espace oklch permettent de calculer toutes ces variantes directement en CSS, à partir d'une seule variable source.
Étape 1 : rappel, pourquoi oklch bat hsl
Une leçon précédente a introduit oklch et color-mix. Le problème de hsl est que ses variations numériques ne correspondent pas à des variations visuelles régulières : +10 de luminosité paraît énorme sur un jaune, presque invisible sur un bleu.
Étape 2 : ce que "perceptuellement uniforme" signifie
oklch est dit "perceptuellement uniforme" : une même variation numérique produit toujours un changement visuel comparable, quelle que soit la teinte de départ.
Étape 3 : le problème avant la couleur relative
Avant cette fonctionnalité, créer une variante plus sombre d'une couleur pour un :hover demandait de calculer manuellement une nouvelle valeur, ou de dupliquer une variable CSS.
Étape 4 : la solution, dériver directement en CSS
oklch(from var(--primaire) calc(l - 0.1) c h) fait cela directement : elle "ouvre" la couleur source en ses composantes, permet de modifier une seule d'entre elles, et reconstruit la couleur.
Bonne pratique
Utilisez color-mix(in oklch, var(--primaire) 20%, white) pour générer une nuance claire d'une couleur de marque, plutôt que de choisir "à l'œil" une nouvelle valeur hexadécimale. Le résultat reste cohérent et prévisible pour toutes les couleurs de la charte.
Étape 5 : le gamut, une limite physique de l'écran
Passons à un autre sujet : un écran ne peut physiquement afficher qu'un sous-ensemble limité de couleurs, son "gamut". Des espaces comme lab ou display-p3 décrivent des couleurs plus saturées que l'ancien sRGB.
| Espace colorimétrique | Particularité |
|---|---|
srgb | gamut standard, compatible partout |
oklch / oklab | perceptuellement uniforme, gamut large |
lab / lch | gamut large, basé sur la perception humaine (CIE) |
display-p3 | gamut étendu, nécessite un écran compatible |
Étape 6 : que se passe-t-il hors gamut
Quand une couleur demandée dépasse ce que l'écran peut afficher, le navigateur la remappe automatiquement vers la couleur affichable la plus proche — un mécanisme transparent mais utile à connaître.
Et ensuite ?
Cette leçon prolonge directement la logique de color-mix : mélanger des couleurs dans un espace perceptuel donne des résultats plus prévisibles. La dernière leçon du cours aborde maintenant les styles d'impression avancés.
Commandes & code
Fonctions de couleur avancées
Calculer des couleurs à partir d'autres couleurs, directement en CSS, avec des espaces colorimétriques plus larges que sRGB.
/* Rappel rapide : oklch et color-mix (déjà vus) restent la base pratique du quotidien */
:root {
--primaire: oklch(60% 0.15 250);
}
/* Relative color syntax : dériver une couleur à partir d'une autre, en CSS pur */
.bouton {
background: var(--primaire);
}
.bouton:hover {
/* part de --primaire, mais réduit la luminosité (l) de 10 points */
background: oklch(from var(--primaire) calc(l - 0.1) c h);
}
.bouton:disabled {
/* réduit juste la saturation (chroma), garde teinte et luminosité */
background: oklch(from var(--primaire) l calc(c * 0.3) h);
}
/* Fonctionne aussi depuis n'importe quel format source */
.variante-rgb {
background: rgb(from #2563eb r g calc(b * 0.8));
}/* Espaces colorimétriques étendus : lab/lch (CIE) et oklab/oklch (perceptuel, plus récent) */
.couleurs-larges {
color: lab(52% 40 59); /* espace CIE Lab -- gamut plus large que sRGB */
color: lch(52% 72 35); /* Lab en coordonnées polaires (teinte explicite) */
color: oklab(60% 0.1 0.05); /* équivalent perceptuellement uniforme, plus prévisible */
color: oklch(60% 0.15 250); /* le plus pratique au quotidien : L, chroma, teinte séparés */
color: color(display-p3 1 0.5 0); /* accès direct à un espace élargi (écrans compatibles) */
}/* color-mix() en détail : interpolation dans un espace colorimétrique choisi */
.mix-1 {
background: color-mix(in oklch, var(--primaire) 70%, white);
/* mélange perceptuellement plus régulier qu'un mix en sRGB classique */
}
.mix-2 {
background: color-mix(in srgb, red 50%, blue);
}
.mix-3 {
/* mélange sans préciser les deux pourcentages : le complément est déduit */
background: color-mix(in oklch, var(--primaire) 30%, transparent);
}
/* Palette générée à partir d'une seule teinte de base */
:root {
--primaire-100: color-mix(in oklch, var(--primaire) 20%, white);
--primaire-300: color-mix(in oklch, var(--primaire) 60%, white);
--primaire-700: color-mix(in oklch, var(--primaire) 80%, black);
}/* Gamut mapping : que se passe-t-il si la couleur demandée n'existe pas sur l'écran ? */
.couleur-hors-gamut {
/* oklch permet un chroma théoriquement illimité -> le navigateur "mappe"
automatiquement vers la couleur affichable la plus proche perceptuellement */
color: oklch(70% 0.4 30); /* chroma très élevé, probablement hors gamut sRGB */
}
@supports (color: color(display-p3 1 1 1)) {
/* dégrader proprement pour les écrans qui supportent un gamut plus large */
.accent {
color: color(display-p3 0.9 0.2 0.2);
}
}Résumé
- La relative color syntax (
oklch(from var(--x) ...)) dérive une teinte/variante sans dupliquer une palette entière à la main. oklch/oklabsont perceptuellement uniformes : une même variation numérique produit un changement visuel cohérent, contrairement àhsl.color-mix(in oklch, ...)produit des dégradés/mélanges plus réguliers qu'un mélange ensrgb.- Un gamut plus large (
lab,display-p3) est automatiquement remappé par le navigateur sur les écrans qui ne le supportent pas.
Exercices pratiques
Mission : générer une charte de couleurs cohérente sans dupliquer 40 valeurs
Objectif : Utiliser la relative color syntax et color-mix() en oklch pour dériver des variantes de couleur cohérentes, et expliquer la limite du gamut.
Contexte
Sur theme.css, --primaire: oklch(60% 0.15 250); est la seule couleur de marque définie. L'équipe design veut générer automatiquement, à partir de cette seule variable : une variante :hover plus sombre, une variante :disabled désaturée, et une nuance très claire --primaire-100 utilisable comme fond de badge. Actuellement, un développeur a codé ces trois variantes à la main en hexadécimal, et elles doivent être refaites à chaque changement de --primaire.