Color models

HSL vs RGB

HSL and RGB describe exactly the same set of colors. Neither is more accurate than the other, and converting between them loses nothing. The difference is what each one makes easy. RGB is built for compositing, HSL for adjusting, and picking the wrong one turns a two second edit into an afternoon.

They are the same cube, described differently

RGB puts a color at a point in a cube. Three axes, red, green and blue, each running 0 to 255. Black is the origin, white is the far corner, and every color you can display sits somewhere inside.

HSL takes that cube and rearranges it into a cylinder. Hue is the angle around it, saturation is the distance from the central grey axis, lightness is the height. Nothing is added and nothing is lost: HSL is a coordinate change, the way polar coordinates are a rearrangement of Cartesian ones.

That is why the conversion is exact in both directions. In this library, running twenty sample colors from RGB to HSL and back moves a channel by at most one step out of 255, and that single step comes from storing the HSL values rounded to two decimals, not from the formula.

What RGB is good at

RGB matches the hardware. A pixel is lit by red, green and blue subpixels, so an RGB triple maps onto what the screen physically does. That has consequences beyond tidiness.

Anything that blends colors mathematically wants RGB. Averaging two colors, alpha compositing, gradient interpolation, image filters, shader work: all of it operates per channel, and all of it behaves predictably in RGB in a way it does not in HSL. Averaging two hues in HSL is not even well defined without deciding which way round the circle you go: the average of 350 degrees and 10 degrees is either 0 or 180, and only one of those is what anyone meant.

RGB is also what hex is. A hex code is nothing but an RGB triple in base 16, two digits per channel, which is why converting between them involves no assumptions and no rounding at all.

What HSL is good at

HSL is good at the edits designers actually make. Make this lighter. Make it less intense. Give me the same color, one step darker, for the border.

In RGB, darkening a color means changing three numbers together and hoping the hue survives. In HSL you move one number. Here is #2563EB with only the lightness changed, every other value held:

#04122F, #0B2C75, #1146BB, #2D69EC, #739BF2, #B9CDF9

And the same color with only saturation changed, which is how you get a muted variant that still belongs to the palette:

This is why design systems are usually specified in HSL even when they ship as hex. A ramp of nine steps from one hue is a loop over lightness values. In RGB it is twenty-seven numbers chosen by hand.

The catch: HSL lightness is not brightness

Here is the thing that trips people up, and it is worth stating bluntly because most explanations skip it.

HSL lightness is a geometric position in the cylinder. It is not a measure of how bright a color looks. Two colors at exactly 50 percent lightness can differ enormously in perceived brightness.

Take pure yellow, hsl(60, 100%, 50%), and pure blue, hsl(240, 100%, 50%). Same saturation, same lightness. Their relative luminance, the measure WCAG uses for contrast, is 0.9278 for the yellow against 0.0722 for the blue, a factor of 12.9.

Both are at 50 percent lightness. One is nearly white, the other is nearly black. Any ramp you build by stepping HSL lightness will therefore look even in some hues and badly uneven in others, and the unevenness is worst exactly where design systems spend most of their time: blues and yellows.

That is the problem OKLCH was designed to fix. Its lightness axis is built to match perception, so equal steps look equal. If you are building a ramp today and your browser support allows it, build it in OKLCH and export hex.

HSV is not HSL

HSV, sometimes called HSB, is a third rearrangement of the same cube and it is easy to confuse with HSL because two of the three letters match. The difference is the top of the range. In HSL, lightness 100 is always white. In HSV, value 100 is the most intense version of the hue, and you get white by dropping saturation to zero instead.

Practically: HSV is what most color pickers use, because a square of saturation against value is a natural picking surface. HSL is what most CSS is written in, because the symmetry around 50 percent lightness makes tints and shades obvious. Neither is better. They answer different questions, and the converter shows both at once so you do not have to keep the distinction in your head.

A rule of thumb

  • Storing or transmitting a color: hex or RGB. It is the canonical form and it does not round.
  • Blending, compositing, interpolating, filtering: RGB, or linear-light RGB if you care about the result being physically right.
  • Adjusting a color by hand: HSL. One number, one intention.
  • Picking a color in an interface: HSV. It is what the square picker is.
  • Building an even ramp or interpolating a gradient without muddy middles: OKLCH.

What none of them tell you

None of these models says anything about whether a combination is readable. Contrast depends on luminance, and none of hue, saturation, lightness or value is luminance. A palette can be beautifully constructed in HSL and fail WCAG AA throughout. Build in whichever model suits the edit, then check the result against the measure that actually governs readability.

Related

Last updated by FusionStudios. Every value on this page is computed by the same functions the tools use. How this is calculated.