Hex, RGB, and HSL Color Codes Explained
Understand hex, RGB, and HSL color codes for the web. Learn how each format works, when to use them, and convert between hex and RGB color values with ease.
Hex, RGB, and HSL are three ways of writing the exact same colors for screens. Once you understand how each works, you can read any color value at a glance and pick the right format for the job.
How digital color works
Screens create color with light, not paint. Every pixel mixes three colored lights — Red, Green, and Blue — and your eye blends them into a single color. This is called additive color: you start in darkness and add light to build colors up.
Each of the three channels has a brightness value from 0 to 255. That range comes from 8 bits per channel (2⁸ = 256 possible levels, counted 0 through 255). With three channels at 256 levels each, a screen can display 256 × 256 × 256 = roughly 16.7 million colors.
Because color is additive, the extremes are easy to predict:
- All channels off (0, 0, 0) = black — no light at all.
- All channels full (255, 255, 255) = white — every light at maximum.
- Equal values in between (128, 128, 128) = a neutral gray.
Turn on just one channel and you get a pure primary: red, green, or blue. Mix two and you get the secondary colors — red + green makes yellow, green + blue makes cyan, red + blue makes magenta.
Hex color codes
A hex code writes those same three channel values using hexadecimal (base-16) digits. The format is #RRGGBB: two digits for red, two for green, two for blue.
Hexadecimal uses sixteen digits — 0123456789ABCDEF — so a single pair runs from 00 (which equals 0) to FF (which equals 255). Each pair is just a channel value in a more compact notation.
| Color | Hex code |
|---|---|
| Red | #FF0000 |
| Green | #00FF00 |
| Blue | #0000FF |
| White | #FFFFFF |
| Black | #000000 |
.button {
background-color: #0000FF; /* pure blue */
color: #FFFFFF; /* white text */
}
Hex codes are case-insensitive, so #ff0000 and #FF0000 are identical.
3-digit shorthand
When both digits of every channel match, you can collapse each pair to one digit. The browser doubles each digit to expand it.
#F00expands to#FF0000(red)#FFFexpands to#FFFFFF(white)#0AFexpands to#00AAFF
Shorthand only works when each channel is a doubled digit, so #FF0000 shortens but #FE0000 cannot.
8-digit hex with alpha
Adding a fourth pair — #RRGGBBAA — sets the alpha channel, which controls opacity. FF is fully opaque, 00 is fully transparent, and 80 is roughly 50%.
.overlay {
background-color: #0000FF80; /* blue at ~50% opacity */
}
RGB and RGBA
The rgb() function expresses the same channel values in plain decimal (0–255). Nothing about the color changes; only the notation does. Modern CSS separates values with spaces, while the older comma syntax still works everywhere.
.box {
color: rgb(255 0 0); /* modern syntax — red */
color: rgb(255, 0, 0); /* legacy comma syntax — same red */
}
To add transparency, use rgba() with a fourth value from 0 to 1, or the modern slash syntax inside rgb() with a percentage:
.tint {
background: rgba(255, 0, 0, 0.5); /* legacy: red at 50% */
background: rgb(255 0 0 / 50%); /* modern: identical result */
}
RGB is handy when you are working with code that already has numeric channel values, or when you want an alpha value without switching formats.
HSL and HSLA
HSL describes color the way a person might think about it, using three intuitive dimensions:
- Hue (0–360°): the position on a color wheel.
0°is red,120°is green,240°is blue, and360°loops back to red. - Saturation (0–100%): how vivid the color is.
100%is fully saturated;0%is gray. - Lightness (0–100%): how much light the color has.
50%gives the pure, most vibrant color;0%is always black and100%is always white, regardless of hue.
.brand {
color: hsl(240 100% 50%); /* pure blue */
color: hsl(240, 100%, 50%); /* legacy comma syntax — same blue */
}
The big advantage of HSL is easy, predictable tweaking. Keep the hue and saturation fixed and change only the lightness to make a tint or shade of the same color:
.swatch { background: hsl(210 80% 50%); } /* base blue */
.swatch--light { background: hsl(210 80% 70%); } /* lighter tint */
.swatch--dark { background: hsl(210 80% 30%); } /* darker shade */
Shifting the hue by a fixed amount also lets you build harmonious palettes — for example, rotating 120° three times gives a balanced trio of colors. HSLA (or the modern hsl(... / alpha) slash syntax) adds opacity the same way RGBA does.
The same colors in every format
These three formats are interchangeable. Here are identical colors written all three ways so you can see they line up exactly:
| Color | Hex | RGB | HSL |
|---|---|---|---|
| Red | #FF0000 | rgb(255, 0, 0) | hsl(0, 100%, 50%) |
| Green | #008000 | rgb(0, 128, 0) | hsl(120, 100%, 25%) |
| Mid blue | #3366CC | rgb(51, 102, 204) | hsl(220, 60%, 50%) |
| White | #FFFFFF | rgb(255, 255, 255) | hsl(0, 0%, 100%) |
| Black | #000000 | rgb(0, 0, 0) | hsl(0, 0%, 0%) |
| Medium gray | #808080 | rgb(128, 128, 128) | hsl(0, 0%, 50%) |
Notice that for grays and white, the hue can be anything because saturation is 0% — with no saturation, hue has no visible effect.
When to use which format
All three produce the same colors, so the choice comes down to convenience:
| Format | Best for |
|---|---|
| Hex | Compact, universally recognized values — the default in most design tools and CSS. |
| RGB / RGBA | Working directly with numeric channel values, or adding alpha to an existing color. |
| HSL / HSLA | Tweaking colors by hand — lightening, darkening, or building related palettes. |
A common workflow is to design with HSL because it is easy to adjust, then ship hex codes because they are short and familiar. You rarely need to convert by hand: our free color picker lets you pick a color visually and instantly copy it as hex, RGB, or HSL, or paste one format and read the equivalents in the others.
A note on alpha and transparency
Alpha is not a color channel — it controls opacity, how much of the background shows through. It works the same across formats: #RRGGBBAA in hex, the fourth value in rgba(), and the slash value in modern rgb() or hsl(). An alpha of 1 (or FF, or 100%) is fully opaque; 0 is fully transparent; values in between let the layers underneath blend through. Reach for alpha when you want soft overlays, subtle tints, or shadows that sit naturally over any background.