The short version
- An HSL color describes a colour by hue, saturation and lightness instead of red, green and blue amounts.
- Hue is an angle on the colour wheel from 0 to 360 degrees, where 0 is red, 120 is green and 240 is blue.
- Saturation runs from 0% (grey) to 100% (full colour), and lightness runs from 0% (black) through 50% (the pure hue) to 100% (white).
- Modern CSS writes it as hsl(262 83% 58%), with an optional alpha after a slash, and every browser in use supports it.
- HSL lightness is not how bright a colour looks to people, so two colours with the same lightness can differ hugely in contrast.
On this page
An HSL color is written as three numbers: hue, saturation and lightness. In CSS, hsl(262 83% 58%) means a hue of 262 degrees (violet), 83% saturation (vivid) and 58% lightness (a little above the midpoint). It is the same violet as #7c3bed, but you can read it. Want it lighter? Raise the last number. Softer? Lower the middle one. That one property, one meaning per number, is why HSL is the friendliest way to write colours by hand.
What hue, saturation and lightness mean
Hue is a position on the colour wheel, given in degrees. Red sits at 0 and again at 360, yellow at 60, green at 120, cyan at 180, blue at 240 and magenta at 300. Moving the hue rotates the colour while keeping its strength.
linear-gradient(90deg, #ff0000 0%, #ffff00 16.67%, #00ff00 33.33%, #00ffff 50%, #0000ff 66.67%, #ff00ff 83.33%, #ff0000 100%)Saturation is how much colour there is. At 0% every hue is the same grey; at 100% it is as vivid as the screen allows. Lightness runs from black at 0% to white at 100%, with the pure hue at 50%. The model is covered more broadly in hue, saturation and brightness, which also explains how HSB in design apps differs from HSL in CSS.
What changing it does
Range
What changing it does
Range
What changing it does
Range
What changing it does
HSL syntax in CSS
There are two spellings. The modern one separates values with spaces and puts alpha after a slash. The older one uses commas and a separate hsla() function. Browsers accept both, and hsl() now takes alpha too, so hsla() is no longer needed. The MDN reference for hsl() lists every form.
.button {
/* modern syntax */
background: hsl(262 83% 58%);
/* with 80% opacity */
background: hsl(262 83% 58% / 0.8);
/* older comma syntax, still valid */
background: hsla(262, 83%, 58%, 0.8);
/* hue can carry a unit */
background: hsl(262deg 83% 58%);
}Build a colour scale by changing lightness
This is where HSL earns its place. Keep hue and saturation fixed, step the lightness, and you have a family of tints and shades that obviously belong together. Here is one violet in seven steps, with the hex each one converts to.
Pair this with CSS custom properties and your whole theme hangs off two numbers. Store the hue and saturation once, then pick a lightness per role. Change the hue variable and the entire interface turns from violet to teal, which is the idea behind CSS variables for theming.
:root {
--brand-h: 262;
--brand-s: 83%;
--brand-50: hsl(var(--brand-h) var(--brand-s) 95%);
--brand-200: hsl(var(--brand-h) var(--brand-s) 85%);
--brand-500: hsl(var(--brand-h) var(--brand-s) 58%);
--brand-800: hsl(var(--brand-h) var(--brand-s) 30%);
}
/* a teal theme is one line */
.theme-teal {
--brand-h: 175;
}Relative colours
Newer browsers also support relative colour syntax, which reads the HSL parts of any colour and lets you adjust them. hsl(from var(--brand) h s calc(l + 15%)) gives a lighter version of whatever the brand colour is, even if it was defined in hex. Check current support on caniuse before relying on it, and keep a plain fallback. For mixing two colours rather than nudging one, color-mix() in CSS is the tool.
Where HSL lies to you
HSL is a rearrangement of RGB, not a model of human vision. Its lightness is a simple average of the brightest and dimmest channels, so it ignores the fact that our eyes see yellow and green as far brighter than blue. The result: two colours with identical HSL lightness can look nothing alike in brightness.
This matters in two places. First, a scale built by stepping HSL lightness will be uneven across hues: a yellow at 50% is far too light for text while a blue at 50% passes easily. Always test real pairs with a contrast checker. Second, gradients and generated palettes that rotate hue at fixed lightness will brighten and dim as they pass through yellow and blue.
HSL is good for
- Reading and editing colours by hand
- Tints and shades of a single hue
- Quick theme switching with variables
- Desaturating a colour for a muted state
Use OKLCH instead for
- Scales that match across different hues
- Predictable contrast from a lightness value
- Gradients that stay even in brightness
- Generated palettes for design systems
OKLCH keeps the same friendly idea (lightness, colourfulness, hue) but measures lightness the way eyes do. If you are starting a new design system, it is the better default; if you are editing existing CSS or want a quick, readable tweak, HSL remains perfectly good.
Converting HSL to hex and back
You rarely need to do the maths, since every design tool and browser devtools panel converts for you: click a colour swatch in Chrome or Firefox devtools and shift through the formats. Under the hood, HSL converts to RGB first, and RGB to hex is simple pair arithmetic, explained in hex to RGB. Expect tiny rounding differences: hsl(262 83% 58%) lands on #7c3bed, one step away from the #7c3aed you may have started with, because whole percentages cannot hit every one of the 16.7 million hex values.
If you design in Gradiently, you seldom touch these numbers at all: a Mark carries its own palette, and on Pro the brand kit stores your colours so the Designer applies them for you.
Questions people ask
What does HSL stand for?
Hue, saturation and lightness. Hue is the angle on the colour wheel, saturation is how vivid the colour is, and lightness is how close it is to black or white.
How do I write an HSL color in CSS?
Use hsl(hue saturation% lightness%), for example hsl(262 83% 58%). Add transparency after a slash: hsl(262 83% 58% / 0.5).
Is hsla() still needed?
No. hsl() accepts an alpha value in every current browser, so hsla() is only kept for older code.
What is the difference between HSL and RGB?
RGB says how much red, green and blue light to mix; HSL says which hue, how vivid and how light. They describe the same colours, but HSL is easier to adjust by hand.
Why do two HSL colors with the same lightness look different?
HSL lightness ignores how sensitive eyes are to each hue, so yellow looks far brighter than blue at the same value. OKLCH fixes this with perceptual lightness.
Written by Gradiently
The team behind Gradiently, a design tool built around Marks: living gradients that make everything you design look like yours.
See our profile