Tutoriels

CSS color-mix() : mélanger des couleurs nativement dans le navigateur

9 min de lecture

Pendant des années, générer des variantes de couleurs en CSS nécessitait soit de coder en dur chaque nuance à la main, soit de recourir à JavaScript et à une bibliothèque de manipulation de couleurs comme chroma.js ou tinycolor2. La fonction CSS color-mix() change tout cela. C'est une fonction CSS native, désormais supportée par tous les navigateurs majeurs, qui mélange deux couleurs ensemble dans une proportion spécifiée — directement dans votre feuille de style, sans JavaScript, sans prétraitement.

Cet article couvre la syntaxe en détail, explique pourquoi le choix de l'espace colorimétrique change tout, présente les cas d'usage pratiques qui rendent color-mix() véritablement utile, et aborde le support navigateur ainsi que les stratégies de fallback.

Qu'est-ce que color-mix() ?

color-mix() est une fonction CSS Color Level 5 qui prend deux valeurs de couleur et une proportion de mélange, et retourne la couleur résultante mélangée. C'est l'équivalent CSS du mélange de deux peintures, mais avec un paramètre supplémentaire crucial : l'espace colorimétrique dans lequel le mélange s'effectue.

Le cas d'usage le plus simple consiste à créer des teintes et des nuances à partir d'une couleur de base. Plutôt que de définir à la main chaque variante de nuance de votre bleu de marque, vous pouvez les dériver dynamiquement :

:root {
  --brand-blue: #2563EB;

  /* Teintes — mélange avec du blanc */
  --brand-blue-light:   color-mix(in oklch, var(--brand-blue) 60%, white);
  --brand-blue-lighter: color-mix(in oklch, var(--brand-blue) 30%, white);

  /* Nuances — mélange avec du noir */
  --brand-blue-dark:    color-mix(in oklch, var(--brand-blue) 80%, black);
  --brand-blue-darker:  color-mix(in oklch, var(--brand-blue) 50%, black);
}

Le bleu de base #2563EB est défini une seule fois. Les teintes et les nuances en sont dérivées. Si la couleur de marque change, toutes les variantes se mettent à jour automatiquement.

Syntaxe et paramètres

La syntaxe complète de color-mix() est :

color-mix(in <color-space>, <color1> [<percentage>]?, <color2> [<percentage>]?)

Le paramètre d'espace colorimétrique

Le premier argument, in <color-space>, est obligatoire et spécifie où le mélange s'effectue. Les options valides incluent :

  • srgb — mélange en RGB standard (le plus familier, mais sujet aux points médians boueux)
  • hsl — mélange en suivant le cylindre HSL
  • hwb — mélange en HWB (Teinte, Blancheur, Noirceur)
  • lab — mélange en CIE Lab (perceptuellement uniforme)
  • oklab — mélange en Oklab (meilleure uniformité que CIE Lab)
  • lch — mélange en LCH (CIE Lab cylindrique)
  • oklch — mélange en OKLCH (Oklab cylindrique, recommandé pour la plupart des usages)
  • display-p3 — mélange en gamme étendue Display P3
  • xyz — mélange en CIE XYZ

Pour la plupart des travaux de design, oklch produit les résultats les plus naturels perceptuellement. Plus de détails dans la prochaine section.

Les arguments de couleur

Les deux valeurs de couleur peuvent être n'importe quelle couleur CSS valide : codes hex, rgb(), hsl(), oklch(), couleurs nommées, ou propriétés personnalisées CSS. Chacune peut optionnellement avoir un pourcentage indiquant quelle part de cette couleur contribue au mélange :

/* Mélange 50/50 (par défaut quand aucun pourcentage n'est donné) */
color-mix(in oklch, #FF5733, #3498DB)

/* 70% première couleur, 30% deuxième */
color-mix(in oklch, #FF5733 70%, #3498DB 30%)

/* 80% première couleur — le pourcentage de la deuxième est déduit à 20% */
color-mix(in oklch, #FF5733 80%, #3498DB)

Si les pourcentages totalisent moins de 100%, le résultat est partiellement transparent. S'ils dépassent 100%, les pourcentages sont normalisés. Si aucun pourcentage n'est spécifié, le mélange est 50/50.

/* Ces formes sont équivalentes */
color-mix(in srgb, blue, red)
color-mix(in srgb, blue 50%, red 50%)
color-mix(in srgb, blue 50%, red)

Mélanger dans différents espaces colorimétriques

Le choix de l'espace colorimétrique n'est pas cosmétique — il modifie fondamentalement la couleur produite. Les mêmes deux couleurs mélangées dans des espaces différents donnent des résultats radicalement différents.

Mélange en sRGB

Le mélange sRGB fonctionne en interpolant les canaux Rouge, Vert et Bleu de façon linéaire. Pour de nombreuses paires de couleurs, cela produit des résultats acceptables, mais les couleurs complémentaires (celles situées de part et d'autre de la roue des couleurs) produisent souvent un point médian désaturé et grisâtre.

/* Mélange orange-rouge et bleu en sRGB */
color-mix(in srgb, #FF5733 50%, #3498DB 50%)
/* Résultat : un violet brunâtre terne — dans la gamme [#9A77B7] */

Le problème est que les canaux RGB des couleurs complémentaires s'annulent mutuellement lors de la moyenne. Le rouge [255, 87, 51] et le bleu [52, 152, 219] produisent un point médian de [154, 120, 135] — un résultat désaturé et délavé.

Mélange en HSL

Le mélange HSL interpole le long de la roue des teintes, ce qui peut causer un problème différent : une rotation de teinte vers des couleurs intermédiaires inattendues.

/* Orange (teinte ~15°) mélangé avec bleu (teinte ~210°) en HSL */
color-mix(in hsl, #FF5733 50%, #3498DB 50%)
/* La teinte s'interpole à ~112° — vous obtenez un intermédiaire verdâtre */

Quand deux couleurs sont éloignées sur la roue des teintes, le chemin le plus court entre elles en HSL peut passer par le vert ou d'autres teintes inattendues. HSL partage également le problème de non-uniformité perceptuelle de hsl() en général — la luminosité du point médian peut ne pas sembler à mi-chemin entre les deux luminosités sources.

Mélange en OKLCH

Le mélange OKLCH est l'approche recommandée pour la plupart des cas d'usage pratiques. Il interpole dans un espace perceptuellement uniforme, ce qui signifie que les couleurs intermédiaires semblent être de véritables points médians visuels — vives, équilibrées et exemptes de dérive de teinte inattendue.

/* Orange-rouge mélangé avec bleu en OKLCH */
color-mix(in oklch, #FF5733 50%, #3498DB 50%)
/* Résultat : un magenta-violet vif — perceptuellement à mi-chemin */

#FF5733 (un orange-rouge chaud) et #3498DB (un bleu vif) mélangés à 50/50 en OKLCH produisent un intermédiaire vibrant et saturé. La teinte s'interpole directement dans la gamme du violet — exactement ce qu'un designer attendrait quand on lui demande de « faire la moyenne » entre orange et bleu.

Mélange en Oklab (chemins de teinte plus courts / plus longs)

Pour l'interpolation de teinte, vous pouvez également spécifier si l'on prend l'arc le plus court ou le plus long autour de la roue des couleurs :

/* Chemin de teinte le plus court (par défaut) */
color-mix(in oklch shorter hue, red, blue)

/* Chemin de teinte le plus long — fait le tour dans l'autre sens */
color-mix(in oklch longer hue, red, blue)

/* Teinte croissante */
color-mix(in oklch increasing hue, red, blue)

Ce contrôle est utile lorsque vous souhaitez délibérément une interpolation qui passe par des teintes intermédiaires spécifiques — par exemple, un dégradé allant du rouge vers le jaune jusqu'au bleu plutôt que par le violet.

Tableau comparatif

Espace colorimétrique Point médian orange + bleu Caractère visuel
srgb Violet grisâtre terne Désaturé, boueux
hsl Verdâtre Dérive de teinte inattendue
lab Violet, moins vif Plus naturel que sRGB
oklch Magenta-violet vif Le plus naturel perceptuellement

Utilisez le Convertisseur de couleurs pour explorer les valeurs OKLCH de vos couleurs spécifiques et prédire leur comportement au mélange.

Cas d'usage pratiques

Créer des états hover et actif

L'une des applications les plus immédiatement utiles est la génération d'états interactifs sans définir de variables séparées pour chacun :

:root {
  --btn-bg: oklch(0.55 0.22 250);  /* Votre bleu de marque */
}

.btn {
  background-color: var(--btn-bg);
}

.btn:hover {
  /* Assombrir de 15% en mélangeant avec du noir */
  background-color: color-mix(in oklch, var(--btn-bg) 85%, black);
}

.btn:active {
  /* Assombrir davantage pour l'état pressé */
  background-color: color-mix(in oklch, var(--btn-bg) 70%, black);
}

.btn:disabled {
  /* Désaturer et éclaircir pour l'état désactivé */
  background-color: color-mix(in oklch, var(--btn-bg) 40%, white);
  opacity: 0.6;
}

Cela élimine le besoin de choisir trois nuances séparées dans un outil de design et de les coder en dur. Les couleurs hover et actif sont dérivées mathématiquement de la base, maintenant la relation cohérente même si la couleur de marque change.

Construire des gammes de couleurs sémantiques

Les systèmes de design ont besoin de couleurs sémantiques — succès, avertissement, danger — qui s'harmonisent avec la palette de marque. color-mix() vous permet de les dériver de la couleur de marque plutôt que de les choisir indépendamment :

:root {
  --brand: oklch(0.55 0.22 250);  /* Bleu de marque */

  /* Succès : mélange avec un vert pur pour conserver une touche d'identité de marque */
  --success: color-mix(in oklch, oklch(0.65 0.22 145) 85%, var(--brand) 15%);

  /* Avertissement : ambre pur — pas de mélange nécessaire ici */
  --warning: oklch(0.75 0.18 70);

  /* Danger : rouge pur */
  --danger: oklch(0.62 0.24 25);

  /* Fonds teintés pour chaque état */
  --success-bg: color-mix(in oklch, var(--success) 12%, white);
  --warning-bg: color-mix(in oklch, var(--warning) 12%, white);
  --danger-bg:  color-mix(in oklch, var(--danger)  12%, white);
}

--success-bg est une très légère teinte du vert succès, dérivée automatiquement. Utilisez-les pour les bannières de notification, les boîtes d'alerte et les états d'erreur des champs de formulaire.

Générer dynamiquement des gammes de nuances complètes

Alors que le Générateur de nuances est l'outil approprié pour créer une gamme complète de 50 à 950 avec des pas perceptuels précis, color-mix() peut générer une approximation utilisable en ligne pour les composants qui ont besoin de quelques variantes :

:root {
  --primary: oklch(0.58 0.20 250);

  --primary-50:  color-mix(in oklch, var(--primary) 8%,  white);
  --primary-100: color-mix(in oklch, var(--primary) 15%, white);
  --primary-200: color-mix(in oklch, var(--primary) 30%, white);
  --primary-300: color-mix(in oklch, var(--primary) 50%, white);
  --primary-400: color-mix(in oklch, var(--primary) 70%, white);
  --primary-500: var(--primary);
  --primary-600: color-mix(in oklch, var(--primary) 85%, black);
  --primary-700: color-mix(in oklch, var(--primary) 70%, black);
  --primary-800: color-mix(in oklch, var(--primary) 55%, black);
  --primary-900: color-mix(in oklch, var(--primary) 35%, black);
  --primary-950: color-mix(in oklch, var(--primary) 20%, black);
}

Dérivation des couleurs de surface en mode sombre

color-mix() est particulièrement précieux pour dériver les couleurs de surface en mode sombre de façon systématique :

@media (prefers-color-scheme: dark) {
  :root {
    --surface-base:     #09090b;
    --surface-elevated: color-mix(in oklch, var(--brand) 8%, #09090b);
    --surface-overlay:  color-mix(in oklch, var(--brand) 12%, #09090b);
  }
}

Mélanger une petite quantité de la couleur de marque dans les surfaces sombres crée une teinte subtile — une technique utilisée par macOS d'Apple et de nombreux systèmes de design modernes pour rendre le mode sombre moins stérile que des surfaces neutres pures.

Comportement du canal alpha

Quand les pourcentages ne totalisent pas 100%, le résultat est partiellement transparent. Cela peut être utilisé délibérément pour créer des variantes translucides :

/* 30% de bleu sur une base transparente — équivalent à rgba à 30% d'opacité */
color-mix(in srgb, blue 30%, transparent)

/* Également valide : transparence nommée de l'autre côté */
color-mix(in oklch, #3B82F6 25%, transparent)

Cela remplace le schéma d'utilisation de rgba() avec un alpha fixe. L'avantage est que la relation d'opacité est explicite dans le pourcentage de mélange, et vous pouvez mélanger avec n'importe quelle couleur — pas seulement la transparence pure.

Support navigateur et fallbacks

En 2026, color-mix() est entièrement supporté dans :

  • Chrome/Edge : depuis la version 111 (mars 2023)
  • Firefox : depuis la version 113 (mai 2023)
  • Safari : depuis la version 16.2 (décembre 2022)

Le support mondial dépasse 90%. Les utilisateurs qui ne peuvent pas voir les résultats de color-mix() sont ceux qui utilisent des navigateurs mobiles très anciens ou des environnements d'entreprise avec des versions de navigateurs verrouillées.

Fallback par amélioration progressive

Les déclarations de propriétés personnalisées CSS se propagent en cascade. Si le navigateur ne supporte pas color-mix(), le fallback de la ligne précédente est utilisé :

:root {
  /* Fallback pour les navigateurs sans color-mix() */
  --btn-hover: #1D4ED8;

  /* Remplacement avec une valeur calculée pour les navigateurs modernes */
  --btn-hover: color-mix(in oklch, var(--btn-bg) 85%, black);
}

Comme les propriétés personnalisées redéclarent la même variable, cela fonctionne comme un schéma d'amélioration progressive. Les navigateurs qui ne supportent pas color-mix() utiliseront la couleur de fallback explicite ; les navigateurs modernes utiliseront la valeur dérivée.

Vous pouvez également utiliser @supports :

.btn:hover {
  background-color: #1D4ED8; /* Fallback */
}

@supports (color: color-mix(in oklch, red, blue)) {
  .btn:hover {
    background-color: color-mix(in oklch, var(--btn-bg) 85%, black);
  }
}

L'approche @supports est plus explicite et plus facile à nettoyer quand vous abandonnerez éventuellement le support des anciens navigateurs.

Points clés à retenir

  • color-mix() mélange deux couleurs nativement en CSS, éliminant le besoin de JavaScript ou de tables de nuances pré-générées pour de nombreux cas d'usage.
  • L'argument in <color-space> contrôle où le mélange s'effectue et affecte dramatiquement le résultat. Utilisez oklch pour la plupart des travaux — il produit des points médians perceptuellement naturels sans désaturation boueuse (problème sRGB) ni dérive de teinte inattendue (problème HSL).
  • Les cas d'usage les plus pratiques sont : les états interactifs (hover, actif, désactivé), la dérivation de couleurs sémantiques, la teinte des surfaces en mode sombre, et la génération de petites gammes de nuances à partir d'une seule variable de base.
  • Quand les pourcentages totalisent moins de 100%, la sortie est partiellement transparente — utile pour créer des variantes d'opacité sans rgba().
  • Le support navigateur couvre tous les navigateurs modernes depuis début 2023. Fournissez une valeur de fallback codée en dur dans la déclaration CSS précédente ou dans un bloc @supports pour les environnements plus anciens.
  • Utilisez le Convertisseur de couleurs pour convertir vos couleurs de marque existantes en OKLCH avant de les utiliser dans color-mix(), et le Générateur de palettes pour visualiser les relations chromatiques harmonieuses avant d'écrire du CSS.

Couleurs associées

Marques associées

Outils associés