01

Considérez HSL comme un modèle d’édition sRGB

CSS Color 4 définit hsl() comme une manière de spécifier une couleur sRGB par sa teinte, sa saturation et sa luminosité. Ce n’est ni un gamut plus large ni un espace perceptuellement uniforme. Le navigateur convertit les coordonnées en composantes rouge, verte et bleue. HSL facilite ainsi les modifications manuelles tout en restant compatible avec HEX et rgb(), mais les canaux sRGB résolus, et non les trois libellés d’entrée, constituent la preuve finale pour comparer, stocker et tester le contraste.

  • La teinte est un angle autour du cylindre HSL : 0deg est le rouge, 120deg le primaire vert sRGB et 240deg le primaire bleu sRGB.
  • Une saturation de 0% donne un résultat achromatique ; 100% utilise la saturation HSL maximale à cette teinte et cette luminosité.
  • Une luminosité de 0% donne le noir, 100% le blanc et 50% est le milieu du modèle, sans garantir une luminosité perçue moyenne.
  • Alpha est séparé : il modifie la composition avec l’arrière-plan, pas les coordonnées stockées.
  • HEX, rgb() et hsl() peuvent représenter le même résultat sRGB dans le gamut malgré des contrôles différents.
02

Écrivez une syntaxe où chaque composante est sans ambiguïté

Le CSS moderne sépare les composantes HSL par des espaces et place alpha après une barre oblique. L’ancienne forme séparée par des virgules demeure compatible, mais mélanger les deux grammaires est invalide. La teinte accepte un angle ; zéro sans unité est également valide, tandis que deg explicite documente mieux un jeton. Les angles bouclent : 0deg, 360deg et 720deg donnent la même teinte. Les exemples sont opaques sauf lorsqu’un alpha est indiqué.

css
:root {
  --accent: hsl(210deg 100% 40%);
  --accent-translucent: hsl(210deg 100% 40% / 60%);
}

/* Valid legacy syntax, retained for compatibility. */
.legacy-example {
  color: hsl(210, 100%, 40%);
}
Entrée HSLHEX résoluDémonstration
hsl(0 100% 50%)#FF00000deg est rouge
hsl(360 100% 50%)#FF0000La teinte boucle
hsl(120 100% 50%)#00FF00Primaire vert sRGB
hsl(240 100% 50%)#0000FFPrimaire bleu sRGB
hsl(210 0% 50%)#808080La teinte n’affecte pas un résultat achromatique
03

La saturation change la coloration, pas l’opacité

Maintenez la teinte à 210deg et la luminosité à 50%, puis réduisez la saturation par pas égaux de 25 points. Le résultat se rapproche de l’axe achromatique tout en restant entièrement opaque. Ce n’est pas une baisse d’alpha : un bleu translucide révèle un arrière-plan inconnu, tandis qu’une couleur HSL moins saturée se résout déjà en un nouveau triplet sRGB opaque. Le tableau applique l’algorithme CSS Color 4 et arrondit les canaux finaux de 8 bits à l’entier le plus proche.

SaturationHSLHEX résoluRGB résolu
100%hsl(210 100% 50%)#0080FF0 128 255
75%hsl(210 75% 50%)#2080DF32 128 223
50%hsl(210 50% 50%)#4080BF64 128 191
25%hsl(210 25% 50%)#60809F96 128 159
0%hsl(210 0% 50%)#808080128 128 128
04

Les pas de luminosité peuvent franchir le seuil du premier plan

Maintenez maintenant la teinte à 210deg et la saturation à 100% tout en changeant la luminosité HSL. La série est simple à générer, mais le premier plan approprié n’est pas constant. Le contraste est calculé depuis chaque HEX arrondi avec la formule de luminance relative sRGB WCAG. AA exige au moins 4,5:1 pour le texte normal. La meilleure option entre noir et blanc est un choix testé pour cette paire, pas une certification d’accessibilité de la page.

LuminositéHEX résoluTexte noirTexte blancChoix AA normal
20%#0033661.67:112.61:1Blanc
30%#004D992.52:18.33:1Blanc
40%#0066CC3.77:15.57:1Blanc
50%#0080FF5.53:13.80:1Noir
60%#3399FF7.14:12.94:1Noir
70%#66B3FF9.46:12.22:1Noir
80%#99CCFF12.44:11.69:1Noir
  • Le premier plan bascule entre 40% et 50% dans cette gamme.
  • Un état hover ou selected issu de la même teinte exige encore ses propres tests de contraste textuel et non textuel.
  • N’arrondissez pas un rapport avant de le comparer à 4,5:1 ; arrondissez uniquement la valeur affichée.
  • En présence d’alpha, de dégradés, d’images ou de superpositions, calculez les couleurs finales rendues avant d’évaluer le contraste.
05

La luminosité HSL n’est pas la luminosité perçue

Le mot luminosité paraît perceptuel, mais la luminosité HSL dérive des extrema des canaux sRGB encodés avec gamma. CSS Color 4 avertit qu’elle ne suit pas la luminosité visuelle d’une teinte à l’autre. Le jaune saturé et le bleu saturé ont tous deux une luminosité HSL de 50%, mais leur luminance relative WCAG et leurs premiers plans utiles sont radicalement différents. Des rotations égales de teinte ne paraissent pas non plus régulières : certaines zones de la roue HSL semblent comprimées, d’autres très espacées.

CouleurHSLHEXLuminance relativeTexte noirTexte blanc
Jaunehsl(60 100% 50%)#FFFF0092.78%19.56:11.07:1
Bleuhsl(240 100% 50%)#0000FF7.22%2.44:18.59:1
06

Évitez les six pièges courants de HSL

  • Ne considérez pas HSL comme un format à gamut étendu : hsl() se résout en sRGB et ne conserve pas une couleur Display P3 hors sRGB.
  • Ne conservez pas un libellé de teinte significatif sur un gris à saturation nulle ; cette composante ne modifie pas le rendu.
  • N’appelez pas une modification de luminosité HSL teinte ou ombre, sauf définition explicite du projet.
  • Ne remplacez pas la saturation par alpha : la première change la couleur opaque, le second sa composition avec un fond.
  • N’attendez pas de rotations angulaires ou de pas de luminosité égaux qu’ils paraissent équidistants ; HSL n’est pas perceptuellement uniforme.
  • N’arrondissez pas HSL à répétition pour écraser un RGB canonique ; les conversions fractionnaires peuvent accumuler une dérive des canaux.

La sérialisation apporte une subtilité supplémentaire. Un navigateur peut exposer une couleur résolue sous forme rgb() même si l’auteur a écrit hsl(), car la couleur utilisée est sRGB. Dans les tests, comparez les canaux résolus ou une représentation volontairement normalisée, pas la chaîne source. Pour les jetons, précisez si HSL est la source éditable canonique ou une présentation dérivée et maintenez ce choix.

07

Livrez les jetons HSL avec des preuves résolues

Un jeu de jetons pratique peut utiliser HSL sans prétendre que chaque pas numérique est sûr. Gardez des noms sémantiques, consignez les coordonnées, résolvez les valeurs sRGB finales pendant le build ou dans la documentation et testez chaque paire réelle. L’exemple utilise du blanc sur la couleur d’action à 40% de luminosité, car cette paire atteint 5,57:1. Le jeton disabled translucide exige encore un arrière-plan connu avant toute conclusion de contraste.

css
:root {
  --action: hsl(210 100% 40%);       /* #0066CC */
  --action-hover: hsl(210 100% 32%);
  --action-disabled: hsl(210 20% 55% / 60%);
  --on-action: #FFFFFF;              /* 5.57:1 on --action */
}

.action {
  color: var(--on-action);
  background: var(--action);
}

.action:hover {
  background: var(--action-hover);
}
  • Conservez une valeur canonique et assez de précision pour reproduire les canaux résolus.
  • Documentez la coordonnée modifiable et le rôle sémantique du jeton obtenu.
  • Exportez un HSL prêt à copier et une valeur HEX ou RGB résolue pour la revue entre outils.
  • Testez séparément default, hover, active, focus, selected et disabled dans les thèmes clair et sombre.
  • Mesurez le contraste sur les couleurs finales composées et gardez le rapport non arrondi dans les données d’audit.
  • Utilisez OKLCH ou un autre espace adapté lorsque des pas perceptuellement réguliers comptent davantage que les contrôles HSL familiers.
  • Liez la méthode de conversion et la spécification afin d’expliquer les futures évolutions du générateur.
S

Sources primaires

Les affirmations factuelles de cet article sont vérifiées dans ces spécifications publiées.

  1. W3C CSS Color 4 — notation HSL
  2. W3C CSS Color 4 — conversion HSL vers sRGB
  3. W3C CSS Color 4 — composantes de couleur sans effet
  4. W3C CSS Color 4 — syntaxes de couleur moderne et historique
  5. W3C WCAG 2.2 — luminance relative
  6. W3C WCAG 2.2 — Contraste (minimum)