HEX (#RRGGBB)
The most common format. Three pairs of hex digits represent red, green, and blue channels from 00 (0) to FF (255).
#0ea5e9 = red 14, green 165, blue 233.
**Shorthand:** When each pair has identical digits, you can write three digits: #aabbcc → #abc.
**With opacity:** 8-digit HEX adds an alpha channel: #0ea5e9cc where cc = 80% opacity (204/255).
**Best for:** Copying from design tools, static values, communication with designers. Not great for manipulation — it's hard to tell what "one shade lighter" looks like in HEX.
RGB (rgb(R, G, B))
rgb(14, 165, 233) — the same colour as #0ea5e9, expressed as decimal values.
**With opacity:** rgba(14, 165, 233, 0.8) — the a stands for alpha, a decimal from 0 (transparent) to 1 (opaque). In modern CSS you can write rgb(14 165 233 / 0.8) without the rgba function.
**Best for:** Dynamic colour values calculated in JavaScript. Easy to interpolate between two colours. Still not intuitive for design decisions.
HSL (hsl(H, S%, L%))
HSL stands for Hue, Saturation, Lightness. This is the first format that maps to how humans think about colour.
- **Hue** — the colour itself, as a degree on the colour wheel: 0/360=red, 120=green, 240=blue
- **Saturation** — how vivid vs grey: 100% is fully saturated, 0% is greyscale
- **Lightness** — how light vs dark: 0% is black, 100% is white, 50% is the "pure" colour
hsl(199, 89%, 48%) — the same sky blue.
**Why HSL is better for design work:** Changing lightness to create hover states, active states, or shade variants is trivial. hsl(199, 89%, 40%) is 8% darker. hsl(199, 89%, 60%) is lighter. Building a palette: pick a hue, vary lightness.
**Limitation:** HSL is perceptually non-uniform. Two colours at the same HSL lightness value don't look equally bright to human eyes. Yellow (60°) at L=50% looks much brighter than blue (240°) at L=50%.
OKLCH — The Modern Standard
OKLCH is a perceptually uniform colour space based on the Oklab model. It uses:
- **L** — lightness (0–1, perceptually linear)
- **C** — chroma (colourfulness, roughly 0–0.4)
- **H** — hue (degrees, same wheel as HSL)
oklch(0.65 0.18 214)
The key difference from HSL: if you hold L constant and rotate H, the brightness genuinely stays constant. You can generate harmonious colour palettes by varying hue while keeping lightness and chroma fixed, and the colours will look like they belong together.
OKLCH also has a wider gamut than sRGB, meaning it can express the vivid colours that modern displays (P3, HDR) are capable of showing.
Browser support is universal in modern browsers (Chrome 111+, Firefox 113+, Safari 15.4+).
When to Use Each
**HEX** — communicating with designers, static design tokens, copying from Figma.
**RGB** — programmatic colour manipulation in JavaScript, interpolation.
**HSL** — design systems where you need to derive shades programmatically (hover states, disabled states). Better than HEX for this.
**OKLCH** — new design systems, dark mode theming, P3 colour support, any situation where perceptual uniformity matters. The best choice for 2026 projects.
WCAG Contrast
When choosing text and background colours, the Web Content Accessibility Guidelines require a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text. NoxaKit's WCAG Contrast Checker calculates this ratio instantly — critical when choosing colours from a palette for a design system.