HEX vs RGB vs HSL: Which Color Format Should You Use?
A practical comparison of HEX, RGB, and HSL color formats: when to use each, how to convert between them, and why one of them is the right choice for your next project.
HEX (#RRGGBB) is for HTML and CSS, where you want a compact, copy-pasteable string. RGB (rgb(R, G, B)) is for code, especially when you need to compute color values programmatically. HSL (hsl(H, S%, L%)) is for design work, because Hue/Saturation/Lightness matches how humans think about color. Convert between them freely with the Uttir color tools — none of them is "more correct," they just serve different audiences.
You have a color. You need to put it in a stylesheet, a design tool, a print spec, or a code constant. The color itself is the same — the numbers just look different depending on the format. This guide explains what HEX, RGB, and HSL actually mean, when to use which, and how to convert between them without losing your mind.
If you just need to convert right now, the HEX to RGB converter and RGB to HEX converter on Uttir do it instantly in your browser. The rest of this article is for when you want to understand what's happening under the hood.
What the three formats actually are
All three formats describe the same thing: a color as a combination of red, green, and blue light. The difference is how the numbers are presented to a human.
HEX: #RRGGBB
HEX is a six-digit hexadecimal number, prefixed with a hash. The first two digits are red, the middle two are green, the last two are blue, each on a scale from 00 to FF (0-255 in decimal). So #FF0000 is full red, #00FF00 is full green, #0000FF is full blue, and #000000 is black.
The shorthand form #RGB expands to #RRGGBB by duplicating each digit. So #F00 is the same as #FF0000, and #09C is the same as #0099CC. The shorthand only works when all three pairs have matching digits, which limits the colors you can express with it, but the ones that work are 20% more compact.
HEX is the format of HTML and CSS. It's how colors appear in design tools, browser DevTools, and pretty much every styling context on the web. The 16.7 million possible HEX values (256 × 256 × 256) is the standard "web-safe" color space, and what most people mean by "the color" of a web page is a specific HEX value.
RGB: rgb(R, G, B)
RGB expresses the same red-green-blue combination as three decimal numbers, each from 0 to 255. rgb(255, 0, 0) is the same red as #FF0000, rgb(0, 255, 0) is the same green as #00FF00, and so on.
RGB also has an alpha-channel variant: rgba(R, G, B, A), where A is opacity from 0 (fully transparent) to 1 (fully opaque). The HEX equivalent uses 8 digits instead of 6: #FF0000CC is 80% opaque red. The new CSS Color 4 syntax also accepts rgb(R G B / A) with the alpha as a slash-separated decimal.
RGB is the format of code. When you need to compute a color (e.g., lighten a brand color by 20%, or generate a palette from a base hue), you do the math in RGB because the channels are independent and the formulas are simple. The Uttir RGB to HEX converter does this conversion; the math is just base-16 to base-10 conversion of the three channels.
HSL: hsl(H, S%, L%)
HSL is a different model of color, designed to be more intuitive for human designers:
- Hue (H) is the color itself, on a 0-360 degree wheel. 0 is red, 120 is green, 240 is blue, 360 is back to red.
- Saturation (S) is how intense the color is, from 0% (gray) to 100% (full intensity).
- Lightness (L) is how light or dark the color is, from 0% (black) to 100% (white), with 50% being the "normal" intensity.
hsl(0, 100%, 50%) is full red, hsl(120, 100%, 50%) is full green, hsl(240, 100%, 50%) is full blue, and hsl(0, 0%, 50%) is medium gray.
HSL also supports alpha: hsla(H, S%, L%, A) or with the new syntax, hsl(H S% L% / A).
HSL is the format of design work. When you're choosing colors, you think in terms of "I want a slightly lighter version of this blue" — that's a lightness adjustment, easy in HSL, awkward in RGB. When you need a palette of related colors, you adjust the hue around the wheel — easy in HSL, painful in RGB. The Uttir color palette generator uses HSL internally for exactly this reason.
When to use which
All three formats express the same color space (sRGB, the standard "computer monitor" color space), so the choice between them is about ergonomics, not capability. Here's the rule of thumb:
- Use HEX when you're writing HTML or CSS by hand, copying from a design tool, or anything where you need a compact, copy-pasteable string. HEX is the de-facto web standard.
- Use RGB when you're computing colors in code — e.g., a function that adjusts brightness, a random color generator, or anything that does math on color channels.
- Use HSL when you're choosing colors, designing a palette, or doing anything where the human-meaningful properties of color (the hue, the saturation, the lightness) matter. The HSL form makes the intent obvious.
There are no hard rules. Many CSS files mix HEX and RGB freely. Design tools often show all three simultaneously (e.g., the macOS color picker shows HEX, RGB, and HSL side by side). The point is to use the format that makes your current task easier.
Converting between them
The conversions are all straightforward math:
HEX to RGB
Parse the six-digit HEX as three pairs of hex digits, then convert each pair to decimal:
#FF5733
→ R: 0xFF = 255
→ G: 0x57 = 87
→ B: 0x33 = 51
→ rgb(255, 87, 51)
RGB to HEX
Convert each channel to two-digit hex, then concatenate:
rgb(255, 87, 51)
→ R: 255 → 0xFF
→ G: 87 → 0x57
→ B: 51 → 0x33
→ #FF5733
RGB to HSL
This one's a bit more involved. The algorithm:
- Normalize RGB to 0-1: divide each by 255.
- Find the max and min of R, G, B.
- Lightness = (max + min) / 2.
- If max == min, the color is gray: saturation = 0, hue = 0.
- Otherwise, calculate the difference (delta) and use it to derive hue and saturation.
The exact formula is well-documented elsewhere (Wikipedia has it), and most languages have a built-in:
// JavaScript
const rgbToHsl = (r, g, b) => {
r /= 255; g /= 255; b /= 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const l = (max + min) / 2;
if (max === min) return [0, 0, l * 100];
const d = max - min;
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
let h;
if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
else if (max === g) h = ((b - r) / d + 2) / 6;
else h = ((r - g) / d + 4) / 6;
return [h * 360, s * 100, l * 100];
};
But the Uttir color picker does this conversion for you, in your browser, for any color you can find.
Common pitfalls
A few things that trip people up:
HSL "lightness" is not the same as "brightness"
Lightness 50% is the "normal" intensity of a color. Lightness 0% is black. Lightness 100% is white. But hsl(240, 100%, 50%) (full blue) and hsl(60, 100%, 50%) (full yellow) don't have the same perceived brightness — yellow looks much brighter to the human eye, even though they have the same HSL lightness. This is why the Uttir contrast checker uses relative luminance, not HSL lightness, when computing WCAG contrast ratios.
For accessibility decisions (which is which text color, which is the background), always use the contrast checker, not the HSL lightness value.
"Web-safe" colors are mostly obsolete
In the 1990s, monitors could only display 256 colors, and a subset of 216 colors was guaranteed to render the same everywhere — the "web-safe" palette. The web-safe HEX values are #000000, #003300, #006600, ..., #00FF00, etc. Modern monitors display millions of colors, and web-safe is no longer a meaningful constraint. Ignore anyone who tells you to stick to web-safe colors.
CSS named colors are limited but useful
CSS has 147 named colors: red, cornflowerblue, rebeccapurple, and so on. They're handy for prototyping but limited in precision. If you need a specific shade, use HEX. If you need a quick throwaway color in a demo, named colors are fine.
HEX shorthand can produce unexpected colors
#F00 is #FF0000 (red). #FB0 is #FFBB00 (orange-yellow), not #FFBB00 if you expected #FB0 to be shorthand for #FFBB00. The shorthand form requires each digit to be duplicated exactly: #ABC → #AABBCC, but #ABD is not valid shorthand. The HEX to RGB converter handles both forms.
The Color 4 spec: new color spaces
Modern CSS supports more color spaces than just sRGB. The CSS Color 4 specification adds color(display-p3 ...), color(rec2020 ...), and others, which can represent colors that sRGB can't. The "Display P3" space, in particular, is what newer Apple devices and high-end Android phones use to display more vivid colors than sRGB supports.
For most web work, sRGB (and therefore HEX, RGB, and HSL) is still the right choice. But if you're designing for high-end displays and you need to take advantage of the wider color gamut, P3 is the way. The Uttir color picker works in sRGB, but the underlying browser APIs support P3 if you need it.
A practical workflow
For a typical web project, the workflow looks like this:
- Pick colors in HSL in your design tool. Designers think in HSL because "slightly less saturated" is a meaningful adjustment; "reduce the G channel by 12" is not.
- Convert to HEX for HTML and CSS. HEX is the standard web format, copy-pasteable, and what shows up in browser DevTools.
- Compute variations in RGB. If you need a hover state that's 10% darker, or a gradient between two colors, do the math in RGB (or HSL) and convert back to HEX for the stylesheet.
- Verify accessibility with the contrast checker. Don't trust your eye for contrast ratios — the WCAG checker uses relative luminance, not HSL lightness, and the difference matters for accessibility.
The color tools on Uttir cover every step: pick a color, convert between formats, check contrast, generate a palette, and build a CSS gradient. All client-side, no upload, no signup.