Le
modèle de couleur HSL
(teinte, saturation, luminosité) offre aux développeurs une façon bien plus lisible de travailler avec les couleurs en CSS par rapport à RGB. Plutôt que de deviner quelle combinaison de rouge, de vert et de bleu va produire la teinte souhaitée, HSL te permet de décrire une couleur comme ton cerveau la perçoit naturellement : tu choisis une couleur, tu définis son intensité, puis tu règles sa clarté. Ce changement de paradigme explique pourquoi de plus en plus de développeurs abandonnent
rgb()
au profit de
hsl()
.
Table des matières
RGB vs HSL - La différence fondamentale
RGB définit une couleur en mélangeant trois canaux lumineux : rouge, vert et bleu, chacun sur une échelle de 0 à 255. Le problème, c'est que c'est ainsi que les écrans restituent les pixels, pas comme les humains perçoivent les couleurs. Si tu veux un bleu légèrement plus clair en RGB, tu dois augmenter les trois canaux dans les bonnes proportions - il n'existe pas de curseur unique à ajuster.
HSL correspond directement à la façon dont on décrit les couleurs au quotidien :
- Teinte (Hue) - la couleur elle-même, exprimée en degrés sur une roue chromatique de 360 degrés. Le rouge est à 0, le vert à 120, le bleu à 240.
- Saturation - l'intensité ou la pâleur de la couleur, de 0% (gris pur) à 100% (couleur vive).
- Luminosité (Lightness) - la clarté ou l'obscurité de la couleur, de 0% (noir) à 100% (blanc), avec 50% représentant la couleur "pure".
Voici le même bleu moyen exprimé dans les deux formats :
/* RGB - what do these numbers even mean at a glance? */
color: rgb(70, 130, 180);
/* HSL - instantly readable: blue hue, moderate saturation, medium lightness */
color: hsl(207, 44%, 49%);
Les deux produisent le même bleu acier. Mais seule la version HSL t'apporte une information utile au premier coup d'oeil. La teinte est à 207 (tirant sur le bleu), la saturation est modérée à 44%, et la luminosité est au milieu à 49%. Tu peux raisonner dessus sans avoir un sélecteur de couleurs ouvert.
| Propriété | RGB | HSL |
|---|---|---|
| Lisible par un humain | Rarement | Oui |
| Éclaircir/assombrir une couleur | Ajuster 3 valeurs | Ajuster la luminosité uniquement |
| Modifier la saturation | Recalculer les 3 valeurs | Ajuster la saturation uniquement |
| Créer une palette de couleurs | Par tâtonnements | Faire pivoter la teinte en degrés |
| Thématisation avec des variables CSS | Verbeux | Propre et prévisible |
Syntaxe HSL en CSS
La fonction CSS
hsl()
est supportée depuis CSS3. La syntaxe moderne (CSS Color Level 4) permet également d'inclure un quatrième paramètre alpha directement dans
hsl()
, ce qui rend
hsla()
largement obsolète aujourd'hui :
/* Classic syntax */
color: hsl(207, 44%, 49%);
/* With alpha (transparency) - old way */
color: hsla(207, 44%, 49%, 0.8);
/* Modern CSS Color Level 4 syntax - commas optional, alpha with slash */
color: hsl(207 44% 49%);
color: hsl(207 44% 49% / 0.8);
color: hsl(207 44% 49% / 80%);
Tous les navigateurs modernes supportent les deux syntaxes. La version sans virgules est la direction que prend CSS, mais la version avec virgules fonctionne partout, y compris sur Internet Explorer 9+.
Pourquoi HSL s'impose dans le développement UI
La vraie puissance de HSL apparaît dès que tu dois générer des variantes d'une couleur - ce qui arrive en permanence dans le développement d'interfaces.
Construire une palette de couleurs en quelques secondes
Imaginons que ta couleur de marque soit un vert vif à
hsl(140, 70%, 45%)
. Tu as besoin d'un état hover, d'un état désactivé et d'une teinte de fond légère. En HSL, tu ne touches qu'une seule valeur à chaque fois :
--color-base: hsl(140, 70%, 45%); /* base green */
--color-hover: hsl(140, 70%, 38%); /* darker - just lower lightness */
--color-disabled: hsl(140, 20%, 65%); /* washed out - lower saturation */
--color-tint: hsl(140, 70%, 92%); /* very light background tint */
Essaie de faire ça de manière prévisible en RGB sans sélecteur de couleurs ouvert. C'est vraiment difficile, car il n'existe pas d'axe isolé à ajuster.
Couleurs analogues et complémentaires
Comme la teinte est un degré sur une roue chromatique, générer des palettes harmonieuses relève de l'arithmétique. Les couleurs analogues sont à moins de 30 degrés les unes des autres. Les couleurs complémentaires sont à 180 degrés d'écart :
--primary: hsl(210, 80%, 50%); /* blue */
--analogous-1: hsl(180, 80%, 50%); /* cyan - 30 degrees left */
--analogous-2: hsl(240, 80%, 50%); /* purple - 30 degrees right */
--complementary: hsl(30, 80%, 50%); /* orange - 180 degrees opposite */
La saturation et la luminosité restent identiques, ce qui donne aux couleurs une cohérence visuelle. C'est exactement ainsi que des design systems comme Tailwind CSS et Material Design génèrent leurs palettes de couleurs de façon programmatique.
Exemples CSS concrets
Propriétés personnalisées CSS avec les composantes HSL
L'un des patterns HSL les plus puissants consiste à séparer les trois valeurs en propriétés personnalisées CSS distinctes. Cela te permet de les réassembler n'importe où et d'ajuster des canaux individuels à la volée :
:root {
--brand-h: 210;
--brand-s: 80%;
--brand-l: 50%;
--brand-color: hsl(var(--brand-h), var(--brand-s), var(--brand-l));
}
.button {
background-color: var(--brand-color);
}
.button:hover {
/* Just override lightness - no need to redefine the whole color */
background-color: hsl(var(--brand-h), var(--brand-s), 40%);
}
.button:disabled {
background-color: hsl(var(--brand-h), 20%, 70%);
}
hsl()
, tu as besoin des virgules :
hsl(var(--h), var(--s), var(--l))
. La syntaxe moderne sans virgules ne fonctionne pas encore avec
var()
à l'intérieur de
hsl()
dans tous les navigateurs.
Générer une gamme tonale complète
Les design systems ont souvent besoin de 9 à 10 nuances d'une même couleur (comme l'échelle de 50 à 950 de Tailwind). Avec HSL, tu peux générer toute la gamme en faisant progresser la luminosité à intervalles réguliers tout en gardant la teinte et la saturation fixes :
:root {
--blue-50: hsl(210, 80%, 95%);
--blue-100: hsl(210, 80%, 87%);
--blue-200: hsl(210, 80%, 76%);
--blue-300: hsl(210, 80%, 65%);
--blue-400: hsl(210, 80%, 55%);
--blue-500: hsl(210, 80%, 50%); /* base */
--blue-600: hsl(210, 80%, 43%);
--blue-700: hsl(210, 80%, 36%);
--blue-800: hsl(210, 80%, 26%);
--blue-900: hsl(210, 80%, 16%);
}
Pour aller plus loin sur les relations entre les formats de couleur, le guide de conversion HEX vers RGB couvre l'ensemble des formats de couleur CSS, y compris quand utiliser chacun d'eux.
États hover, thématisation et mode sombre
États hover et focus
HSL rend les états hover trivials. Au lieu de définir une couleur complètement différente, tu ajustes simplement la luminosité :
.btn-primary {
background: hsl(210, 80%, 50%);
transition: background 0.2s ease;
}
.btn-primary:hover { background: hsl(210, 80%, 43%); }
.btn-primary:active { background: hsl(210, 80%, 36%); }
.btn-primary:focus-visible {
outline: 3px solid hsl(210, 80%, 70%);
}
Chaque état est clairement lié à la couleur de base. Un collègue qui lit ce code comprend immédiatement la relation entre les différents états.
Thématisation avec des variables HSL
HSL est le socle de la thématisation CSS moderne. En exposant uniquement la teinte comme variable, tu permets aux utilisateurs ou aux administrateurs de changer l'ensemble du schéma de couleurs d'une application en modifiant un seul nombre :
/* Default theme: blue */
:root {
--theme-hue: 210;
}
/* Green theme - just swap the hue */
[data-theme="green"] {
--theme-hue: 140;
}
/* Purple theme */
[data-theme="purple"] {
--theme-hue: 270;
}
/* All components use the same hue variable */
.button { background: hsl(var(--theme-hue), 75%, 50%); }
.link { color: hsl(var(--theme-hue), 75%, 40%); }
.badge { background: hsl(var(--theme-hue), 75%, 92%); color: hsl(var(--theme-hue), 75%, 25%); }
.focus-ring { outline-color: hsl(var(--theme-hue), 75%, 65%); }
Mode sombre avec HSL
Le mode sombre est là où HSL prend vraiment l'avantage. Au lieu de maintenir deux palettes de couleurs entièrement séparées, tu inverses les valeurs de luminosité en conservant la même teinte :
:root {
--bg: hsl(210, 20%, 98%); /* near-white background */
--text: hsl(210, 20%, 15%); /* near-black text */
--card: hsl(210, 20%, 93%); /* slightly darker card */
}
@media (prefers-color-scheme: dark) {
:root {
--bg: hsl(210, 20%, 10%); /* flip: near-black background */
--text: hsl(210, 20%, 90%); /* flip: near-white text */
--card: hsl(210, 20%, 15%); /* slightly lighter card in dark */
}
}
Remarque que la teinte (210) et la saturation (20%) ne changent jamais. Seule la luminosité s'inverse. Cela permet au mode sombre de conserver l'identité visuelle du design, simplement inversée - ce qu'un bon mode sombre doit faire.
Support navigateur et compatibilité
HSL bénéficie d'un excellent support navigateur. La fonction
hsl()
est disponible depuis :
- Chrome 1 (2008)
- Firefox 1 (2004)
- Safari 3.1 (2008)
- Internet Explorer 9 (2011)
- Edge 12 (2015)
La syntaxe moderne sans virgules (
hsl(210 80% 50%)
) et la syntaxe alpha avec slash (
hsl(210 80% 50% / 0.5)
) font partie de la
spécification CSS Color Level 4
et sont supportées par tous les navigateurs modernes depuis 2023. Si tu dois encore supporter IE11 (ce qui est rare à ce stade), reste sur la syntaxe avec virgules.
hsl()
avec virgules fonctionne dans tous les navigateurs que tes utilisateurs utilisent probablement. La syntaxe moderne avec espaces fonctionne dans Chrome 90+, Firefox 89+ et Safari 14.1+, couvrant bien plus de 95% de l'utilisation mondiale des navigateurs.
Tu peux toujours utiliser un sélecteur de couleurs pour convertir entre les formats HSL, RGB et HEX quand tu dois croiser des valeurs ou transmettre des couleurs à des outils qui n'acceptent qu'un seul format.
HSL vs OKLCH - Et après ?
Si tu veux aller plus loin que HSL, OKLCH mérite d'être connu. C'est un espace colorimétrique perceptuellement uniforme, ce qui signifie que des pas numériques égaux en luminosité ou en chroma correspondent à des variations visuellement égales pour l'oeil humain - ce que HSL ne garantit pas pleinement.
Le problème avec HSL, c'est que deux couleurs ayant la même valeur de luminosité peuvent paraître très différentes en termes de clarté perçue. Par exemple,
hsl(60, 100%, 50%)
(jaune) semble bien plus lumineux que
hsl(240, 100%, 50%)
(bleu), même si les deux ont une luminosité de 50%. OKLCH corrige ce problème.
/* HSL - same lightness, different perceived brightness */
color: hsl(60, 100%, 50%); /* yellow - looks very bright */
color: hsl(240, 100%, 50%); /* blue - looks much darker */
/* OKLCH - same lightness, actually looks the same to the eye */
color: oklch(0.75 0.18 90); /* yellow-ish */
color: oklch(0.75 0.18 260); /* blue-ish - genuinely similar perceived brightness */
OKLCH supporte également les
couleurs à gamme étendue
(couleurs d'affichage P3) qui dépassent la plage sRGB à laquelle HSL est limité. Le support navigateur pour
oklch()
est solide en 2024 : Chrome 111+, Firefox 113+, Safari 15.4+.
Pour la plupart des projets actuels, HSL reste le choix le plus pragmatique : lisible, maintenable, universellement supporté, et une amélioration considérable par rapport à RGB. OKLCH est le bon choix quand tu construis un design system nécessitant des ratios de contraste mathématiquement cohérents ou que tu vises des écrans à gamme étendue.
Si tu explores visuellement les relations entre couleurs pendant la construction de ta palette, l' outil color explorer te permet d'expérimenter avec les valeurs HSL et de voir en temps réel comment les rotations de teinte, les variations de saturation et les changements de luminosité interagissent.
Choisis tes couleurs HSL sans tâtonnements
Notre sélecteur de couleurs te permet de régler visuellement la teinte, la saturation et la luminosité, puis de copier directement le résultat HSL dans ton CSS - sans calcul mental.
Essayer le sélecteur de couleurs →
Tu n'as pas besoin de tout réécrire, mais ça vaut la peine de passer à HSL pour toutes les nouvelles définitions de couleurs, surtout quand tu utilises des propriétés personnalisées CSS. Les gains les plus importants se font sentir quand tu construis ou maintiens un design system, que tu crées des états hover, ou que tu implémentes le mode sombre. Mélanger RGB et HSL dans le même projet est tout à fait du CSS valide - les navigateurs gèrent les deux sans aucune différence de performance.
Non, il n'y a aucune différence de performance significative. Le navigateur convertit tous les formats de couleur CSS en une représentation interne au moment du parsing, donc que tu écrives
hsl(207, 44%, 49%)
ou
rgb(70, 130, 180)
, le moteur de rendu les traite de façon identique après cette étape initiale. Le choix relève entièrement de l'expérience développeur et de la maintenabilité, pas des performances à l'exécution.
Oui, et c'est l'un des cas d'usage les plus puissants de HSL en JavaScript. Tu peux stocker la teinte, la saturation et la luminosité comme des nombres séparés, puis construire la chaîne de couleur dynamiquement :
element.style.color = `hsl(${hue}, ${saturation}%, ${lightness}%)`
. Cela rend les animations, le changement de thème et les contrôles de couleur interactifs bien plus simples à implémenter qu'avec les canaux RGB, où tu aurais besoin de conversions mathématiques pour obtenir les mêmes effets.
HSL (teinte, saturation, luminosité) et HSB/HSV (teinte, saturation, luminance/valeur) sont des modèles de couleur différents, même s'ils partagent l'axe de teinte. En HSL, une luminosité de 50% donne la couleur pure et entièrement saturée. En HSB, une luminance de 100% donne la couleur pure. Les deux modèles produisent des résultats différents pour les mêmes valeurs de saturation et de luminosité/luminance. CSS utilise spécifiquement HSL - HSB/HSV est courant dans les outils de design comme Photoshop et Figma, mais n'est pas un format CSS natif.
La conversion de HEX vers HSL passe par une étape intermédiaire en RGB : on convertit d'abord les paires HEX en valeurs RGB (0-255), on les normalise entre 0 et 1, puis on applique la formule de conversion HSL. En pratique, la plupart des développeurs utilisent un sélecteur de couleurs, un outil de design comme Figma, ou le sélecteur de couleurs des DevTools du navigateur pour faire ça instantanément plutôt que de calculer à la main. Les DevTools te permettent de cliquer sur n'importe quelle pastille de couleur et de basculer entre les représentations HEX, RGB et HSL.
Oui, OKLCH est plus fiable pour le travail d'accessibilité car il est perceptuellement uniforme - des pas égaux dans son canal de luminosité correspondent à des variations de clarté perçue égales. Cela facilite la construction de palettes de couleurs où les ratios de contraste sont prévisibles quelle que soit la teinte. Avec HSL, le jaune à 50% de luminosité paraît bien plus lumineux que le bleu à 50% de luminosité, ce qui peut créer des surprises en matière d'accessibilité. Pour la conformité aux contrastes WCAG, OKLCH offre des résultats plus prévisibles lors de la construction de palettes de couleurs accessibles.