HEX, RGB, and HSL: Understanding CSS Colour Formats
CSS supports multiple colour formats: hexadecimal, RGB, HSL, and more. Learn what each format means, how to convert between them, and when to use each in your stylesheets and design work.
The Three Core CSS Colour Formats
CSS lets you express colours in several ways. Three formats dominate day-to-day web development:
- HEX (
#7c3aed) — Hexadecimal notation, used everywhere - RGB (
rgb(124, 58, 237)) — Red, Green, Blue channel values - HSL (
hsl(263, 84%, 58%)) — Hue, Saturation, Lightness
All three describe the same colour — they are just different ways of specifying the same point in colour space. Understanding how they relate helps you pick colours deliberately, rather than guessing hex values.
Hexadecimal (HEX) Colour
Format
#RRGGBB /* full 6-digit */
#RGB /* shorthand — #7c3aed → cannot shorten; #aabbcc → #abc */
#RRGGBBAA /* with alpha (CSS Colors Level 4) */
Each pair of hex digits represents one colour channel (Red, Green, Blue) as a value from 00 to FF (0 to 255 in decimal).
#7c3aed
↑↑ = 7c = 124 decimal (red channel)
↑↑= 3a = 58 decimal (green channel)
↑↑= ed = 237 decimal (blue channel)
Shorthand
A 3-digit hex (#RGB) is valid when each pair of digits is identical. #aabbcc → #abc. #7c3aed cannot be shortened.
When to Use HEX
- Design tokens and brand colours (e.g., a company's
#1a1a2eprimary) - Copying colours from Figma, Sketch, or other design tools (they output hex by default)
- Working with static colour values that don't need programmatic manipulation
RGB — Red, Green, Blue
Format
rgb(124, 58, 237)
rgb(124 58 237) /* space-separated (modern CSS) */
rgb(124 58 237 / 0.5) /* with alpha */
rgba(124, 58, 237, 0.5) /* legacy alpha syntax */
Each channel is an integer from 0 to 255, or alternatively a percentage from 0% to 100%.
Understanding the Channels
- Red: 0 = no red, 255 = maximum red
- Green: 0 = no green, 255 = maximum green
- Blue: 0 = no blue, 255 = maximum blue
Pure colours:
Red: rgb(255, 0, 0)
Green: rgb(0, 255, 0)
Blue: rgb(0, 0, 255)
White: rgb(255, 255, 255)
Black: rgb(0, 0, 0)
When to Use RGB
- When working programmatically with colour channels (e.g., interpolating colours in an animation)
- When passing colour values to Canvas API or WebGL
- When mixing colours mathematically
- When an API or library expects numeric R/G/B values
HSL — Hue, Saturation, Lightness
Format
hsl(263, 84%, 58%)
hsl(263deg 84% 58%) /* explicit degree unit */
hsl(263deg 84% 58% / 0.5) /* with alpha */
Understanding the Channels
Hue (0–360): The base colour, expressed as an angle around the colour wheel:
- 0° / 360° = Red
- 30° = Orange
- 60° = Yellow
- 120° = Green
- 180° = Cyan
- 240° = Blue
- 270° = Violet / Purple
- 300° = Magenta
Saturation (0–100%): How vivid the colour is.
- 0% = Greyscale (no colour)
- 100% = Fully saturated (pure, vivid colour)
Lightness (0–100%): How light or dark the colour is.
- 0% = Black
- 50% = The "pure" colour
- 100% = White
Why HSL is the Designer's Friend
HEX and RGB are intuitive for machines but not for humans. It is hard to predict what #7c3aed looks like without a colour picker. HSL is different — you can reason about it directly:
- Want a darker shade? Lower the lightness:
hsl(263, 84%, 40%)vshsl(263, 84%, 58%) - Want a muted version? Lower the saturation:
hsl(263, 30%, 58%) - Want the complementary colour? Add 180° to the hue:
hsl(83, 84%, 58%)
This makes HSL ideal for:
- Generating colour palettes programmatically (vary lightness to create tints and shades)
- Theming (light/dark mode can be a lightness flip)
- Building design systems with consistent tonal relationships
Example: Generating a Tonal Palette
/* A 5-step palette from one HSL base */
--colour-50: hsl(263, 84%, 95%);
--colour-100: hsl(263, 84%, 88%);
--colour-200: hsl(263, 84%, 75%);
--colour-500: hsl(263, 84%, 58%); /* base */
--colour-700: hsl(263, 84%, 40%);
--colour-900: hsl(263, 84%, 20%);
Alpha Transparency
All three formats support transparency via an alpha channel (0 = fully transparent, 1 = fully opaque):
/* All equivalent for a 50% transparent violet */
#7c3aed80 /* hex with alpha */
rgb(124 58 237 / 0.5) /* modern rgb */
rgba(124, 58, 237, 0.5) /* legacy rgba */
hsl(263 84% 58% / 0.5) /* modern hsl */
The percentage 0.5 can also be written as 50%:
hsl(263 84% 58% / 50%)
Modern CSS: oklch and oklch()
CSS Colors Level 4 introduced oklch and oklab, perceptually uniform colour spaces that produce more visually consistent gradients and palette generation. While not universally used yet, they are supported in all modern browsers:
/* oklch(lightness chroma hue) */
color: oklch(0.58 0.22 263);
The advantage of oklch over HSL is that adjusting lightness changes the perceived brightness consistently across hues. In HSL, a green at 50% lightness looks far brighter than a blue at 50% lightness.
Converting Between Formats
HEX → RGB
Split the hex string into three pairs and convert each from base-16 to base-10:
#7c3aed → R: 0x7c = 124, G: 0x3a = 58, B: 0xed = 237
→ rgb(124, 58, 237)
RGB → HSL
The conversion involves:
- Normalise R, G, B to 0–1 by dividing by 255
- Find min and max of the three values
- Lightness L = (max + min) / 2
- Saturation S depends on L and the (max - min) delta
- Hue H is calculated from which channel is the maximum
The formula is defined in the CSS spec — most developers use a library function or a tool like the one below rather than doing it by hand.
In JavaScript
// Using CSS.supports() to check support
// Or libraries like chroma.js, tinycolor2
// Manual HEX → RGB
function hexToRgb(hex) {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return { r, g, b };
}
Use the Colour Converter
The Colour Code Converter on DevGizmo converts between HEX, RGB, and HSL instantly. Enter any format and get all three outputs — plus a colour preview — with a single click.