You tweak a button hover color and write rgb(52, 152, 219). The designer says "a bit brighter, a bit bluer." You stare at the three numbers, unsure which one to change. With a different notation it is much simpler: hsl(207, 90%, 61%). Move lightness from 61% to 71% and "a bit brighter" is done. RGB and HSL describe the same color, just from different angles.
In this article
1. RGB: the additive model built for machines
RGB stands for Red, Green, Blue. It breaks any color into the brightness of three lamps — red, green and blue — each dialed from 0 to 255. Monitors, phones and projectors all glow with these three lamps, which makes RGB the color language the hardware actually runs.
That is also why it is called additive: all lamps off is black, all on is white. It works the opposite way from mixing paint, which gets darker as you combine pigments while light gets brighter as you stack it.
From 0 (no red light) to 255 (red at full strength).
The eye is most sensitive to green, so most colors that read as "natural" lean on it for brightness.
Mostly responsible for the warm/cool balance: less reads warm, more reads cool.
/* A clean sky blue */
background: rgb(52, 152, 219);
2. HSL: intuitive coordinates built for humans
HSL approaches the same color through three dimensions the eye perceives directly: H for hue (what color), S for saturation (how vivid), L for lightness (how bright). It does not care how the display produces the light, only what you see.
What the three dimensions control
- H hue: 0 to 360 degrees around a color wheel. 0 is red, 120 is green, 240 is blue.
- S saturation: 0% is gray, 100% is the most vivid.
- L lightness: 0% is black, 100% is white, and around 50% sits the pure color.
At L 50% the color is at its most saturated; push it up toward white and it lightens, pull it down toward black and it deepens. So in hsl(207, 90%, 61%) the 61% is a moderately bright blue: 71% is clearly brighter, 41% clearly deeper, all with a single value to change.
/* The same sky blue, written in HSL */
background: hsl(207, 90%, 61%);
3. Converting between the two notations
The two convert because they are different coordinates of the same color space. The formula is not hard, but doing it by hand invites mistakes, so in practice a tool is the better route. For RGB→HSL, three steps are enough:
The logic of RGB to HSL
- Normalize 0–255 to 0–1:
r = R / 255, and the same for g and b. - Find the max and min, compute the delta Δ, then
L = (max + min) / 2. - H is determined by which channel is the max, and S follows from L.
HSL→RGB is equally deterministic. In day-to-day work it is rarely computed by hand —
| Color | RGB | HSL |
|---|---|---|
| Sky blue | rgb(52,152,219) | hsl(207,90%,61%) |
| Pure red | rgb(255,0,0) | hsl(0,100%,50%) |
| Grass green | rgb(46,204,113) | hsl(145,63%,49%) |
| Gold | rgb(241,196,15) | hsl(48,89%,50%) |
| Purple | rgb(155,89,182) | hsl(285,40%,53%) |
4. Which to pick when writing CSS
Neither is better; it is about which is handier for the task.
| Scenario | Use | Why |
|---|---|---|
| Copying a fixed value from a design | RGB / HEX | design tools export exactly this |
| Brand or theme color | HSL | easy to brighten or saturate as a whole |
| Hover and active states | HSL | move only L to build layers |
| Light/dark themes via CSS vars | HSL | calc() on L feels natural |
A useful pattern: store the brand color as HSL variables and derive the hover state with calc(var(--l) + 8%). Darker and lighter versions come out on their own, without hunting for extra color values.
:root {
--brand-h: 207;
--brand-s: 90%;
--brand-l: 61%;
}
.btn {
background: hsl(var(--brand-h), var(--brand-s), var(--brand-l));
}
.btn:hover {
background: hsl(var(--brand-h), var(--brand-s), calc(var(--brand-l) + 8%));
}
5. Why HSL is easier to tune with
Tuning a color is really "moving through a space." RGB is unfriendly to humans here: going "bluer" means dropping R, dropping G and raising B at the same time — three axes coupled together. HSL splits hue, saturation and lightness into three independent knobs, and moving one leaves the others alone.
- Switch families: rotate H and leave S and L untouched; the whole palette changes hue, so reskins go quickly.
- Unify the feel: fix H and L, move only S, and a gray-to-vivid ramp appears.
- Build layers: fix H and S, move only L, and a button’s default, hover and pressed states start to feel like a set.
In one line: RGB is the machine language, HSL is the human one. A fixed color is fine in RGB, but whenever there is tuning involved, HSL almost always saves effort.
Next time the designer asks for "a bit brighter, a bit bluer," there is no need to stare at three numbers. Switch to HSL, hand brightness to L and hue to H, and a single change is visible right away. RGB and HSL are not either/or — they are two labels on the same set of colors, and knowing which one to reach for is usually enough.