Guide
HSL Color Explained: A Practical Guide for Designers
HSL describes color the way a human eye thinks about it: pick a hue, decide how vivid it should be, decide how bright. Once that maps to instinct, hex starts to feel like assembly language.
What HSL stands for
HSL is short for hue, saturation, and lightness. In CSS it looks like this:
color: hsl(265, 75%, 63%);
background: hsl(180 100% 50% / 0.5);
Three numbers, in that order. They describe a single color, exactly the same color you can also write as #7C5CDF or rgb(124, 92, 223) for the first example. Different notation, identical pixel.
Hue: where on the wheel
Hue is an angle from 0 to 360 degrees on the color wheel. The wheel is the same one you see in design apps: red at 0°, yellow at 60°, green at 120°, cyan at 180°, blue at 240°, magenta at 300°, and back to red. The angle is the only thing that decides which family the color belongs to.
- 0° / 360° — red
- 30° — orange
- 60° — yellow
- 120° — green
- 180° — cyan
- 210° — sky blue
- 240° — pure blue
- 270° — violet
- 300° — magenta
Adding 180° to a hue gives its complementary color. Adding 120° twice gives a triadic palette. The math that drives the palette generator on the home page is just hue arithmetic.
Saturation: how vivid
Saturation is a percentage from 0% to 100%. At 100% the color is fully vivid. At 0% it collapses to a shade of gray — the hue is still recorded but you can't see it, because there is no color information left.
Two things to internalise:
- Lowering saturation pulls a color toward neutral, which is what design systems usually want for backgrounds, borders, and muted text.
- "Saturation" in HSL is not the same as "saturation" in HSV or in image-editor sliders — they use different math. The CSS value is HSL specifically.
Lightness: how bright
Lightness is also 0% to 100%, but the scale is non-intuitive at first:
- 0% — pure black, regardless of hue or saturation.
- 50% — the most vivid version of the chosen hue.
- 100% — pure white, regardless of hue or saturation.
That means raising lightness past 50% does not make the color "more colorful" — it pushes it toward white. To get a brighter, still-saturated color, leave lightness near 50–60% and adjust saturation instead. This is the single most useful thing to remember about HSL.
When HSL beats hex
Hex is great for: copying a single value out of a design tool. HSL is better for almost everything else. Three concrete cases:
1. Building a color scale
To produce a 5-step gray scale in hex, you'd guess at six characters per step and tweak in a tool. In HSL, the same scale is obvious:
--gray-100: hsl(220, 14%, 96%);
--gray-300: hsl(220, 13%, 82%);
--gray-500: hsl(220, 10%, 60%);
--gray-700: hsl(220, 12%, 35%);
--gray-900: hsl(220, 18%, 14%);
Hue is locked. Saturation barely moves. Lightness does the work. The result feels intentional rather than improvised.
2. Hover and active states
"Make this button slightly darker on hover" is a one-line change in HSL: subtract 8% from lightness. In hex you'd be eyeballing it.
3. Theming
For a brand color at hsl(265, 75%, 63%), a sensible "dim" variant might be hsl(265, 35%, 45%): same hue, less saturation, less lightness. Anyone reading the stylesheet immediately understands the relationship.
The math behind the conversion
Going from HSL to RGB involves a chroma value C = (1 − |2L − 1|) × S, an offset, and a six-segment mapping based on which 60° slice of the wheel the hue lives in. The full algorithm is in the CSS Color Module specification. The takeaway: HSL is a transformation of the same RGB cube, not a different color space, so any HSL value can be expressed exactly as RGB and vice versa.
The home converter runs this conversion live — type a hex code and the HSL chip below the swatch updates as you type.
HSLA and the alpha channel
Modern CSS accepts an alpha value alongside HSL using a slash:
background: hsl(265 75% 63% / 0.25);
Alpha is a number from 0 (fully transparent) to 1 (fully opaque). The older hsla() function still works for backwards compatibility but is no longer required — modern browsers accept the alpha inside the regular hsl() function. For a deeper look at how alpha actually composites against the background, see the RGBA and transparency guide.
Common mistakes
- Treating lightness like brightness. A "brighter" red is usually more saturated red, not lighter. Push saturation toward 100% before pushing lightness past 60%.
- Forgetting the percent signs.
hsl(265, 75, 63)is invalid; saturation and lightness need%. - Using HSL for accessibility decisions. Two colors with the same lightness can have very different perceived contrast — lightness in HSL is geometric, not perceptual. For accessibility, calculate the actual contrast ratio (the home checker does this) instead of comparing lightness values.
- Mixing degrees and percentages. CSS now accepts
hsl(265 75% 63%)with spaces and no commas. Both syntaxes are valid; pick one and stay consistent in a codebase.
HSL vs OKLCH and modern alternatives
HSL has been in CSS since 2010. It is intuitive but not perceptually uniform: equal numeric jumps in lightness do not produce equal jumps in perceived brightness, and equal hue rotations do not produce equally distinct colors. Newer formats — oklch(), lch(), lab() — fix this and are now widely supported. They are the better choice for serious color systems where uniform progression matters. HSL is still the right choice when you want a quick, readable adjustment in a stylesheet, and it will not stop being supported. The CSS color formats reference walks through the differences in detail.
Quick checklist
- Hue first — pick the family on the wheel.
- Saturation second — decide how much color you want versus gray.
- Lightness third — and remember 50% is the peak, not 100%.
- Use HSL for related colors; use a perceptual format like OKLCH for serious systems.
- Use the contrast ratio, not lightness, for accessibility checks.