The same colour can be written four common ways. They are not rivals — each is good at a different job, and knowing which to reach for saves a lot of fighting with colour.
HEX and RGB — the same thing, said differently
#3d8bf5 and rgb(61, 139, 245) are identical colours. HEX packs the three channels into
six hexadecimal digits; RGB writes them as decimals. That is the only difference.
- HEX is compact and universal. Every tool understands it, and it is the right default for a fixed brand colour you will paste around.
- RGB is easier to reason about when you want to nudge one channel — “a bit less red” is
obvious in
rgb()and cryptic in hex. It is also the form you need for transparency, viargb(61 139 245 / 50%).
Neither tells you anything useful about the colour as a human sees it. You cannot look at
#3d8bf5 and know it is a medium, fairly saturated blue without decoding it. That is what the
next two formats are for.
HSL — colour the way people think
hsl(214, 90%, 60%) describes the same blue as hue, saturation, lightness — which maps onto
how we actually talk about colour.
- Hue (0–360°) is the colour’s position on the wheel: 0 red, 120 green, 240 blue.
- Saturation (0–100%) is how vivid it is, from grey to full colour.
- Lightness (0–100%) runs from black through the pure hue at 50% to white.
This makes HSL wonderful for adjustment. Want a darker version of a colour? Drop the lightness and leave hue and saturation alone. Want a whole range of a colour? Step the lightness. Almost every “shades of X” tool is just HSL with the lightness changing.
HSL has one serious flaw, and it is the reason OKLCH exists.
Why HSL lies about lightness
In HSL, yellow at 50% lightness and blue at 50% lightness are supposedly equally light. Look at them side by side and the yellow is obviously far brighter.
HSL’s “lightness” is a geometric convenience, not a measure of how light a colour looks. So when you build a scale by stepping HSL lightness evenly, the steps come out visually uneven — bunched up in some places, jumping in others. Gradients between distant hues sag through a muddy, dark middle for the same reason.
You can work around it by hand, but you are fighting the format.
OKLCH — lightness that matches your eye
oklch(61.5% 0.164 250) describes the colour in a space built so that equal numbers look
equally different.
Its three parts mirror HSL — lightness, chroma (roughly saturation), hue — but the lightness is perceptual. Two colours with the same OKLCH lightness genuinely look equally light, whatever their hue.
That one property fixes both of HSL’s problems:
- Scales built by stepping OKLCH lightness look evenly spaced, because they are evenly spaced to the eye. This is why modern design systems generate their colour ramps in OKLCH.
- Gradients interpolated in OKLCH stay bright and even across the whole transition — no muddy middle.
OKLCH is supported in every current browser, so you can ship it directly in CSS today.
Which to use
| Situation | Reach for |
|---|---|
| A fixed brand colour to paste around | HEX |
| Adjusting one channel, or adding alpha | RGB |
| Quick by-hand tweaks, simple shade steps | HSL |
| Scales, gradients, anything generated or systematic | OKLCH |
The honest short version: use HEX for constants, and OKLCH for anything where a colour needs to be calculated rather than just stated. HSL sits comfortably in between for quick manual work.