samedi 28 mars 2026

Générer automatiquement des palettes via CSS avec OKLCH

Nous sommes en train de mettre la dernière main à un thème pour Dotclear dérivé de celui que nous utilisions sur le site de l’Auberge des blogueurs. Il sera en démo ici au cours de la journée.

Le problème

À l’auberge, il était facile d’attribuer des couleurs différenciées (en l’occurrence selon l’auteurice) puisque nous disposions de leur liste. Pour chaque nouvelle autrice ou auteur on indiquait sa couleur et voilà.

Ici, il s’agit d’un thème distribué : je ne connais pas le nombre de catégories, ni leur nom, ni leur identifiant. Idem pour les auteurices. Par ailleurs, nous souhaitions que le ou la proprio du blog puisse choisir une ambiance dominante de couleurs vives ou de couleurs douces, en harmonie entre elles et reconnaissables si l’on passe d’une gamme à l’autre. Je ne pouvais donc pas préciser telle couleur pour telle catégorie (ou auteurice).

Ah et puis il fallait une palette pour le mode dark aussi.

OKCLH à la rescousse

Dans mes découvertes récentes après mon interruption de veille des techno web depuis cinq ou six ans, je suis tombée sur le modèle de couleurs OKLCH. Pour ce que je cherchais à faire c’est idéal.

Vous pouvez aller lire l’article en lien ci-dessus pour des informations plus complètes que je vais simplifier ici. Dans oklch, l représente la luminosité, c la chromie, h la teinte (h pour hue). Selon le but recherché, en conservant un ou deux des paramètres et en faisant bouger le troisième, on obtient des gammes visuellement cohérentes. Je vous invite à aller jouer avec les curseurs pour vous en rendre compte.

J’ai donc défini quatre principes :

  • Un point de départ avant calcul propre à chaque catégorie : la teinte (h) 155.
  • Pour les couleurs douces, une luminosité (l) à 0.75 et une chromie (c) à 0.06 (résultat du point de départ).
  • Pour les couleurs vives, une luminosité (l) à 0.48 et une chromie (c) à 0.15 (résultat du point de départ).
  • Pour les couleurs du mode dark, je mélange les couleurs douces avec un gris-bleu très sombre (ma couleur de fond dans ce mode).

Une fois cela établi, le seul paramètre que je fais bouger c’est celui de la teinte, quelle que soit la gamme.

Le code

Pour faire varier la teinte, je m’appuie sur l’identifiant numérique de la catégorie, dont je me sers pour « faire bouger le curseur » avec des pas de 55 pour que les couleurs ne soient pas proches les unes des autres (donc un step avec juste le numéro de la catégorie ne serait pas suffisant) et pas un nombre qui ferait retomber trop vite sur les mêmes couleurs (donc pas un nombre entier d’une division de 360). Voici comment « bouge » la valeur de hue :

--hue: calc(h + (55 * id_de_la_cat));

Je ne détaille pas comment récupérer la valeur numérique de la catégorie1, c’est trop spécifique à Dotclear mais vous pourrez toujours télécharger le thème et en étudier les sources si vous en avez besoin2. Si bien que pour chaque élément (ici ma_div) possédant un identifiant numérique on aura trois variables à utiliser selon les contextes :


.ma_div {
  --hue: calc(h + (55 * id_de_la_div));

  /* gamme douce */
  --specific-color-muted: oklch(0.75 0.06 var(--hue)); 
  /* gamme vive */
  --specific-color-vibrant: oklch(0.48 0.15 var(--hue));
  /* gamme dark mode */
  --specific-color-dark: color-mix(oklch(0.75 0.06 var(--hue)), var(--body-bg));
}

/* affectation selon le contexte */
.muted .ma_div {
    --specific-color: --specific-color-muted;
  }
.vibrant .ma_div {
    --specific-color: --specific-color-vibrant;
  }
.dark .ma_div {
    --specific-color: --specific-color-dark;
  }

/* Utilisation */
.ma_div header {
  background-color: var(--specific-color);
  color: oklch(from var(--specific-color) round(1.21 - L) 0 0);
}

Note : la dernière ligne est la cerise sur le gâteau de ce qui est possible avec OKLCH, calculer automatiquement le texte noir ou blanc selon la couleur de fond. Merci Kevin Hamer .

J’ai fait un code pen sur ce principe, bien que je n’ai pas pu reproduire la récupération de la valeur de l’identifiant d’une catégorie avec les seuls outils proposés mais ça peut vous donner une idée en point de départ de vos propres expérimentations. Aussi, je ne sais pas pourquoi mais les couleurs sont vachement plus moches sur cette démo qu’en vrai !


  1. Pour le moment, seuls les navigateurs chromium acceptent de traiter un nombre dans un attribut comme une valeur numérique, ce qui permettrait d’utiliser directement attr(data-cat_id type(<number>). Comme ça ne pouvait être utilisé partout, j’ai eu recours à un hack en introduisant la définition de la variable dans un attribut style inline. Spa beau mais ça marche en attendant que tous les navigateurs sachent interpréter un attribut en number. ↩︎

  2. Parution dans les jours qui viennent et il y aura un billet ici. ↩︎