Kodokon kodokon.com

Couleurs et fonctions avancées : oklch, color-mix, min/max

Exploitez les espaces colorimétriques perceptuels, la syntaxe des couleurs relatives et les fonctions mathématiques typées pour des systèmes de design calculés par le navigateur.

10 min · 3 questions

Ouvrir cette leçon dans Kodokon

Le défaut structurel de hsl() : sa luminosité n'est pas perceptuelle. hsl(60 100% 50%) (jaune) paraît éclatant quand hsl(240 100% 50%) (bleu) paraît sombre, à L identique. oklch corrige cela : sa composante L (0 à 1) mesure la clarté perçue, C le chroma (saturation absolue, 0 à environ 0.37) et H l'angle de teinte. Changer H à L constant conserve la luminosité perçue : vos déclinaisons de palette deviennent enfin prévisibles. Combiné à la syntaxe des couleurs relatives (from), le navigateur dérive lui-même vos variantes hover, muted ou dark.

CSS
:root {
  --brand: oklch(0.65 0.19 255);
  --dark: oklch(from var(--brand) calc(l - 0.15) c h);
  --muted: oklch(from var(--brand) l calc(c / 2) h);
  --accent: oklch(from var(--brand) l c calc(h + 180));
}
Une seule couleur source, trois dérivées calculées : les canaux l, c, h sont exposés comme variables locales.

oklch peut décrire des couleurs hors gamut sRGB, voire hors Display-P3. Que fait le navigateur quand l'écran ne sait pas les afficher ? Pas un écrêtage brutal canal par canal : la spécification prescrit un gamut mapping qui réduit progressivement le chroma en préservant la clarté et la teinte, jusqu'à rentrer dans le gamut cible. Vous pouvez cibler les écrans large gamut explicitement avec @media (color-gamut: p3). Autre outil de mélange : color-mix(), dont le premier argument - l'espace d'interpolation - change réellement le résultat : un mélange in srgb entre bleu et jaune vire au gris, quand in oklch traverse des teintes vives.

CSS
.badge {
  background: color-mix(in oklch, crimson 70%, white);
  border-color: color-mix(
    in oklch,
    var(--brand),
    transparent 60%
  );
}
Mélanger avec transparent produit une variante translucide sans dupliquer la couleur en rgba.

min(), max() et clamp() sont des fonctions mathématiques typées : elles acceptent de mélanger des unités incompatibles à l'analyse (rem + vw) car la résolution se fait au moment du calcul des valeurs utilisées, quand le viewport est connu. clamp(MIN, VAL, MAX) est strictement équivalent à max(MIN, min(VAL, MAX)) - conséquence de spécification : si MIN dépasse MAX, c'est MIN qui gagne. Pour la typographie fluide, incluez toujours une part en rem dans la valeur centrale : un font-size: clamp(1rem, 2.5vw, 3rem) sans rem ignorerait le zoom texte de l'utilisateur, un vrai problème d'accessibilité.

CSS
h1 {
  font-size: clamp(1.5rem, 1.1rem + 2vw, 3rem);
}
.sidebar {
  width: min(30%, 20rem);
  padding-left: max(1rem, env(safe-area-inset-left));
}
Typographie fluide accessible et gouttières qui respectent les encoches des écrans mobiles.

Quiz de validation

Vérifiez que vous avez bien retenu les points clés de cette leçon.

  1. Quel avantage décisif oklch offre-t-il par rapport à hsl ?
    • Une syntaxe plus courte à écrire
    • Une clarté L perceptuellement uniforme d'une teinte à l'autre
    • La garantie de rester dans le gamut sRGB
    • Le seul espace à supporter un canal alpha
  2. Que fait le navigateur quand une couleur oklch dépasse le gamut de l'écran ?
    • Il ignore la déclaration et garde la couleur précédente
    • Il applique un gamut mapping qui réduit surtout le chroma
    • Il écrête chaque canal RGB indépendamment, sans autre traitement
  3. Dans clamp(MIN, VAL, MAX), que se passe-t-il si la valeur MIN calculée dépasse MAX ?
    • La déclaration devient invalide et est ignorée
    • MAX l'emporte et plafonne le résultat
    • MIN l'emporte, car clamp se développe en max(MIN, min(VAL, MAX))