CSS lets you write the same color three different ways β #3498db, rgb(52, 152, 219), or hsl(204, 70%, 53%) β and all three describe the exact same shade of blue. The difference isn't in what they can represent, it's in what's easy to do with each one.
HEX: Compact and Universal
A HEX code packs red, green, and blue into six characters, two per channel, in base-16. It's the most common format in CSS because it's short, and every design tool β from Figma to Photoshop β exports colors as HEX by default. The tradeoff: HEX numbers aren't intuitive to read. Nobody can look at #2c3e50 and immediately picture the color.
How to Read a HEX Code
Split the six characters into three pairs β red, green, blue β and convert each pair from base-16 to decimal. In hexadecimal, the digits run 0β9 then aβf (a = 10, f = 15), and each pair is first digit Γ 16 + second digit:
2cβ 2 Γ 16 + 12 = 44 (red)3eβ 3 Γ 16 + 14 = 62 (green)50β 5 Γ 16 + 0 = 80 (blue)
So #2c3e50 is rgb(44, 62, 80) β low values with blue slightly highest, which is a dark, slate blue-grey. HEX also has a three-digit shorthand where each digit is doubled: #f80 means #ff8800. Only colors whose pairs repeat can be shortened.
RGB: Explicit Channels, Built-In Transparency
RGB spells out the same three channels as plain decimal numbers (0β255), which makes it easier to reason about programmatically β most image and color APIs work in RGB internally. Its real advantage in CSS is rgba(), which adds a fourth value for opacity: rgba(52, 152, 219, 0.5) is the same blue at 50% transparency. HEX has an 8-digit alpha variant too (#3498db80), but it's less widely recognized by developers reading the code.
HSL: Built for Adjusting Colors by Hand
HSL separates a color into hue (the actual color, 0β360Β°), saturation (how vivid), and lightness (how light or dark). This is the format to reach for when you're building a color palette or theme: keep the hue fixed and just change the lightness to get a lighter or darker variant of the same color, e.g. hsl(204, 70%, 53%) β hsl(204, 70%, 80%) for a lighter tint β no guessing at new RGB numbers required. hsla() adds the same alpha-transparency option as RGBA.
The three HSL values are easiest to understand with a few landmarks:
- Hue is a position on a colour wheel: 0Β° is red, 120Β° is green, 240Β° is blue, and 360Β° wraps back to red. 60Β° is yellow, 180Β° cyan, 300Β° magenta.
- Saturation at 0% is a pure grey, whatever the hue; 100% is the most vivid version of that hue.
- Lightness at 0% is always black and 100% always white; 50% gives the βpurestβ version of the colour.
Side-by-Side Comparison
| HEX | RGB | HSL | |
|---|---|---|---|
| Example | #3498db | rgb(52 152 219) | hsl(204 70% 53%) |
| Value ranges | 00βff per channel | 0β255 per channel | 0β360Β°, 0β100%, 0β100% |
| With 50% opacity | #3498db80 | rgb(52 152 219 / 50%) | hsl(204 70% 53% / 50%) |
| Easy to read? | No | Somewhat | Yes |
| Easy to adjust by hand? | No | Hard to predict | Yes |
| Design tool exports | Default almost everywhere | Common | Less common |
Note the HEX alpha: the last pair is opacity on the same 00βff scale, so 80 (128) is 128 Γ· 255 β 50%, cc (204) is 80%, and ff is fully opaque.
Modern CSS Color Syntax
Current CSS lets you write rgb() and hsl() with spaces instead of commas, and add opacity after a slash. In this modern syntax, rgba() and hsla() are simply older aliases β rgb() and hsl() accept an alpha value on their own:
/* Legacy comma syntax */
color: rgba(52, 152, 219, 0.5);
color: hsla(204, 70%, 53%, 0.5);
/* Modern space syntax β same colours */
color: rgb(52 152 219 / 0.5);
color: hsl(204deg 70% 53% / 50%);
Both forms work in all current browsers. Just donβt mix them: a comma in one place and a space in another inside the same function is invalid, and the whole declaration is ignored. The hue can be written as a plain number or with the deg unit, like other CSS units covered in our complete guide to CSS units.
Building a Palette with HSL
Because hue, saturation and lightness are separate, a whole colour scale can come from a single hue value stored in a custom property:
:root {
--brand-h: 204;
--brand-s: 70%;
--brand-100: hsl(var(--brand-h) var(--brand-s) 92%);
--brand-300: hsl(var(--brand-h) var(--brand-s) 72%);
--brand-500: hsl(var(--brand-h) var(--brand-s) 53%);
--brand-700: hsl(var(--brand-h) var(--brand-s) 35%);
--brand-900: hsl(var(--brand-h) var(--brand-s) 18%);
}
Change --brand-h from 204 to 150 and the whole scale turns from blue to green, keeping the same light-to-dark steps. Doing the same with HEX would mean recalculating every value.
One limitation: HSL lightness isnβt perceptual. A yellow at 50% lightness looks much brighter than a blue at 50% lightness, so check text contrast for each shade rather than assuming equal lightness means equal readability. Newer colour functions such as oklch() are designed to fix this and are supported in current browsers, but HSL remains the most widely understood option.
Common Mistakes
- Putting the alpha in the wrong place in HEX. CSS uses
#RRGGBBAAβ alpha last. Some platforms (such as Android colour resources) use#AARRGGBB, so copying a value between them can swap your colours. - Leaving out the % signs in legacy HSL.
hsl(204, 70, 53)is invalid in comma syntax; saturation and lightness need percentages. - Using opacity instead of an alpha colour. The
opacityproperty fades the element and all of its children, including text. For a see-through background with solid text, use an alpha colour onbackground-color. - Expecting conversions to round-trip exactly. HSL values are usually rounded to whole numbers, so converting HEX β HSL β HEX can shift a channel by one. Keep your original HEX as the source of truth.
Which Should You Use?
- HEX β hardcoded brand colors, design handoffs, anywhere compactness matters.
- RGB/RGBA β whenever you need transparency and want the numbers to stay easy to read at a glance.
- HSL/HSLA β building a color system, generating shades/tints programmatically, or fine-tuning a color's brightness without changing its hue.
Need to move between formats for a specific color? Our Color Converter converts HEX, RGB, and HSL instantly, with a live swatch preview. Working specifically with transparency? Try our dedicated HEX to RGBA Converter.
Frequently Asked Questions
Do HEX, RGB and HSL produce different colours on screen?
No. They are three ways of writing values in the same sRGB colour space, so equivalent values render identically. Any visible difference comes from rounding during conversion, not from the format.
Is HEX case-sensitive?
No. #3498DB and #3498db are the same colour. Many teams use lowercase for consistency, but browsers accept either.
Which format is best for accessibility?
None is more accessible than another β contrast between text and background is what matters. HSL makes it easier to darken or lighten a colour to reach a required contrast ratio, but always check the final pair with a contrast checker.
Can I use colour names like βtomatoβ instead?
Yes, CSS supports named colours such as tomato and rebeccapurple. Theyβre handy for prototypes, but there are only a limited set, so real brand colours almost always need HEX, RGB or HSL.
Try it yourself: paste your main brand colour into the Color Converter, copy its HSL value, and try changing only the lightness to create a lighter background tint and a darker hover state that clearly belong to the same family.
