HEX, RGB, HSL and HSV: A Developer's Guide to Color Formats
Why designers think in HSL, browsers store RGB and your design file exports HEX. How the color models relate and when each one is the right tool.
A designer sends you #2563EB. Your CSS framework wants rgb(). The design system documentation describes colors in HSL. Your image editor's picker shows HSV. They can all describe exactly the same color, and knowing how they relate saves a lot of guesswork.
This guide explains each format, why each exists, and when to use which. You can convert between all four in the Color Picker and Converter.
RGB: how screens make color
Screens produce color by mixing red, green and blue light. RGB describes a color as the intensity of each channel. In standard 8-bit color each channel runs from 0 to 255, giving 256 x 256 x 256, about 16.7 million combinations.
color: rgb(37, 99, 235);
color: rgb(37 99 235 / 50%); /* modern syntax with alpha */
rgb(0, 0, 0) is black, rgb(255, 255, 255) is white, and equal values in all channels give a grey.
RGB maps directly to hardware, which makes it the natural storage format, but it is unintuitive to edit. To make a color "a bit lighter" you have to change all three numbers in the right proportions.
HEX: RGB in base 16
HEX is just RGB written as hexadecimal. Each pair of digits is one channel from 00 (0) to FF (255):
#2563EB
25 = 37 (red)
63 = 99 (green)
EB = 235 (blue)
So #2563EB and rgb(37, 99, 235) are identical. HEX is compact and easy to copy, which is why design tools export it. CSS also accepts a three-digit shorthand where each digit is doubled (#F80 is #FF8800), and eight-digit HEX with alpha (#2563EB80). The RedBison converter's HEX field takes the six-digit form.
HSL: color as humans describe it
In 1978, Alvy Ray Smith published "Color Gamut Transform Pairs" at SIGGRAPH, describing HSV and related models designed to make color selection intuitive. HSL follows the same idea:
- Hue: the position on a color wheel, from 0 to 360 degrees. 0 is red, 120 green, 240 blue.
- Saturation: from 0% (grey) to 100% (full color).
- Lightness: from 0% (black) through 50% (pure color) to 100% (white).
color: hsl(221 83% 53%);
HSL makes common design tasks simple. To create a hover state, lower the lightness a few points. To create a muted variant, lower saturation. To build a palette of tints and shades, keep hue and saturation fixed and step the lightness. This is why many design systems, including the CSS variables behind shadcn/ui, define their tokens in HSL.
HSV: the picker's model
HSV (also called HSB, for brightness) uses the same hue and saturation idea, but its third axis is value: 0% is black and 100% is the brightest version of the color. The difference from HSL is where pure color sits:
| Pure red | White | Black | |
|---|---|---|---|
| HSL | hsl(0 100% 50%) | lightness 100% | lightness 0% |
| HSV | hsv(0 100% 100%) | saturation 0%, value 100% | value 0% |
HSV maps neatly onto the familiar square-and-slider color picker: the slider chooses hue, and the square sets saturation horizontally and value vertically. That is why Photoshop, Figma and many image editors show HSB. CSS does not support HSV directly, so you convert to HSL, RGB or HEX for the web.
The catch: lightness is not perceived lightness
HSL and HSV are simple transforms of RGB, and they do not account for how human vision works. Our eyes are much more sensitive to green than blue. Compare:
hsl(60 100% 50%), yellowhsl(240 100% 50%), blue
Both have 50% "lightness", but yellow looks far brighter. A palette generated by stepping HSL lightness can therefore look uneven across hues, and text contrast can vary wildly.
Two consequences follow:
- Accessibility contrast uses its own formula. WCAG calculates relative luminance from linearized RGB with weights of roughly 0.2126 for red, 0.7152 for green and 0.0722 for blue. Never assume two colors have similar contrast because their HSL lightness matches. Check with a contrast checker.
- Perceptual color spaces exist to fix this. CSS Color Level 4 adds
oklch()andoklab(), based on Björn Ottosson's Oklab model from 2020, where equal steps in lightness look equal. They are supported in current versions of all major browsers and are increasingly used for design tokens.
Which format when?
| Task | Best format |
|---|---|
| Copying from a design file | HEX |
| Adding transparency in CSS | rgb() with alpha, or 8-digit HEX |
| Building tints, shades and states by hand | HSL |
| Working in an image editor's picker | HSV / HSB |
| Perceptually even palettes | OKLCH |
| Storing colors in a database or API | HEX or RGB integers |
A workflow for design tokens
When I set up colors for a project, I take the brand HEX values, convert them to HSL to understand their hue and saturation, then build a scale of lighter and darker steps for backgrounds, borders, hover states and text. Every text and background pair goes through a contrast check before it ships. The Color Picker gives you all four formats at once, plus a quick palette of related shades to start from.
Related tools
- Contrast Checker to test text and background colors against WCAG
- Color Picker from Image to sample colors from a screenshot or photo
- CSS Gradient Generator to blend colors