HEX vs RGB vs HSL: Which Color Format to Use When
Early in my freelancing days I spent most of an afternoon building hover states by editing hex codes directly. The brand blue was #2D6CDF, and I kept guessing toward "the same but darker" — #2D5CBF? #1C5BCE? — pasting each attempt in, squinting at the button, guessing again. What I finally shipped wasn't darker at all; it had drifted toward purple, and the client noticed before I did.
The fix, once a designer took pity on me, was changing one number.
That afternoon is the whole HEX vs RGB vs HSL question in miniature. These aren't three competing standards where you pick a winner — they're three notations for the same value, each designed for a different task, and most color frustration comes from working in the wrong one. By the end of this post you'll know what each notation is good at, and which one to switch into the moment you need to change a color rather than just store it.
HEX vs RGB vs HSL: three spellings of the same number
Your screen makes every color by mixing three channels of light — red, green, and blue — each at an intensity from 0 to 255. A color, to the computer, is just those three numbers. Everything else is notation:
| Notation | The same blue | Reads as |
|---|---|---|
| HEX | #2D6CDF | three bytes in base-16: 2D red, 6C green, DF blue |
| RGB | rgb(45, 108, 223) | the same three bytes in decimal |
| HSL | hsl(219, 74%, 53%) | a hue angle, a saturation, a lightness |
HEX and RGB are literally the same numbers in different bases — 2D is 45, 6C is 108, DF is 223, two hex digits per channel. (If the base-16 part feels like a magic trick, our hexadecimal guide shows why two hex digits always equal exactly one byte.) HSL describes the same point with different coordinates: which direction around the color wheel (hue 219° lands in the blues), how far from gray (74% saturated), and where it sits between black and white (53% lightness).
Think of a song that exists as sheet music, as guitar tab, and as a recording. Same song, note for note — but you hand the sheet music to the session violinist, the tab to the self-taught guitarist, and the recording to everyone else, because notation gets chosen per reader, not per song. Color formats work the same way, and converting between them is as faithful as transcription: run any value through the HEX to RGB converter and back, and nothing about the color changes.
What HEX and RGB are each actually for
HEX is the storage and handoff format. It's compact, it's unambiguous, and it's what design tools export and what you can grep for across a codebase. Six characters, pastes cleanly everywhere. That's real value — just notice that every one of those virtues is about transporting a color, not adjusting one.
RGB earns its keep when code touches the channels directly: canvas pixel data, image processing, computing an average or a blend. If you're doing arithmetic on color components, decimal channels are what you want — that's the moment to split a hex code apart, or pack channel values back together with the RGB to HEX tool when the math is done.
One myth worth clearing: transparency doesn't force a format anymore. Modern CSS accepts alpha in all three — #2D6CDFCC, rgb(45 108 223 / 0.8), hsl(219 74% 53% / 0.8). The old "convert to rgba() for opacity" rule only applies if you support genuinely old browsers.
Why you can't "darken" a hex code by eye
Here's what I was actually doing wrong that afternoon. "Darker" is a change along one perceptual dimension — lightness — but in HEX and RGB that dimension is smeared across all three channels at once. Darkening #2D6CDF correctly means scaling 45, 108, and 223 down proportionally, and nobody does proportional scaling in their head, in base-16, per attempt. When I nudged 6C down to 5C, I wasn't darkening the blue; I was rebalancing the mix and shifting the hue. Toward purple, as it turned out.
HSL puts each perceptual dimension on its own dial. The brand blue is hsl(219, 74%, 53%), so:
- Hover state, darker: hsl(219, 74%, 43%) — lightness down ten, roughly #1D55BF.
- Disabled state, washed out: hsl(219, 30%, 80%) — saturation down, lightness up.
- Focus ring, same family but pale: hsl(219, 74%, 88%).
Every variant keeps hue 219, which is what makes a palette read as one family instead of a coincidence. Run any hex code through the HEX to HSL converter and this kind of edit becomes a ten-second job — or grab all three notations at once from the Color Picker while choosing the base color in the first place. The hover state I fumbled for forty minutes is one lightness change. That's the receipt.
Gradients reward the same thinking: two saturated endpoints blended channel-by-channel in RGB pass through the middle of the color cube, which is why quick gradients so often look muddy at the center. Build yours in the Gradient Generator and actually look at the midpoint before shipping it.
Where HSL lies to you
Now the counterargument, because HSL has a real flaw: its lightness is mathematical, not perceptual. hsl(60, 100%, 50%) is pure yellow and hsl(240, 100%, 50%) is pure blue — identical 50% lightness on paper, wildly different brightness to a human eye. The yellow practically glows. So never assume two colors with equal L have equal contrast against your text; check the actual contrast ratio every time.
The fix exists: OKLCH, a newer CSS color space where equal lightness genuinely looks equally light across hues, and browser support is solid now. I still reach for HSL for day-to-day variant work — the mental model is simpler and, honestly, my muscle memory is the laggard here — but if you're building a design system's color scale from scratch in 2026, OKLCH is worth the learning curve.
The workflow that actually works
- Pick visually. Choose the base color in a picker and take all three notations from the same place.
- Edit in HSL. Any time the task is "same color, but ___" — darker, muted, paler — convert to HSL, change one dial, convert back.
- Store consistently. Keep whatever format your codebase already uses; a stylesheet that's 90% hex should stay hex. One caveat from experience: rounding means a value that round-trips hex → HSL → hex can drift by a digit, so treat one format as the source of truth and derive the rest from it.
You might be thinking you don't touch colors often enough to need a workflow. That was my position too, right up until the afternoon it cost me.
Try it yourself
Everything runs in your browser — nothing uploaded:
- Color Picker — pick a color visually, get HEX, RGB, and HSL at once.
- HEX to RGB — split a hex code into its decimal channels.
- RGB to HEX — pack channel values back into a hex code.
- HEX to HSL — the conversion to make before you start editing a color.
- Gradient Generator — build CSS gradients and sanity-check the midpoints.
Conclusion
The afternoon I lost to nudging hex digits wasn't a knowledge gap about color — it was a notation error. HEX and RGB are storage formats: compact, precise, perfect for moving a color between tools and files, and nearly useless for changing one by eye. HSL is the editing format, with hue, saturation, and lightness each on its own dial. All three name the same number and conversion is free in both directions, so use each for the job it was drawn for: store in hex, compute in RGB, adjust in HSL — and check contrast with your own eyes, because that's the one thing no notation does for you.
Try the tools
Frequently Asked Questions
Are HEX and RGB the same thing?
Effectively yes — they're the same three channel values written in different bases. #2D6CDF and rgb(45, 108, 223) are one color: 2D is 45, 6C is 108, DF is 223, with two hex digits per channel. Converting between them changes nothing about the color.
Which is better for CSS: HEX, RGB, or HSL?
The browser treats them identically once parsed, so there's no performance or rendering difference. Choose by task — hex for storing and sharing values, HSL when you're building variants of a color — and keep one consistent format within a stylesheet.
Why do developers prefer HSL for theming?
Because each perceptual dimension gets its own number. A darker hover state, a washed-out disabled state, and a pale focus ring are all one-value edits from the base color, and keeping the hue fixed makes the whole palette read as one family.
Can I use transparency with all three formats?
Yes. Modern CSS accepts alpha everywhere: #2D6CDFCC as eight-digit hex, rgb(45 108 223 / 0.8), and hsl(219 74% 53% / 0.8). The old rule that you must convert to rgba() for opacity only applies to very old browsers.
What is OKLCH and should I use it instead of HSL?
OKLCH is a newer, perceptually uniform color space where equal lightness values genuinely look equally bright across hues — HSL's main weakness. Browser support is solid in modern browsers. HSL remains fine for quick variant edits; OKLCH is worth adopting for new design-system color scales.
CodeUtilityKit Team builds free, privacy-first developer tools that run entirely in your browser. Every guide is written and reviewed by developers who use these tools daily.