The four formats
HEX — the web's native shorthand
Six hex digits encoding three byte-sized channels: #RRGGBB. Compact, easy to copy, used everywhere on the web. #FF6B35 is a vivid orange. Two extra digits add alpha: #FF6B3580 is the same orange at 50% opacity.
Use it when. Writing CSS, sharing colors in chat, naming swatches in Figma. It's the universal lingua franca.
RGB — how screens actually work
Three channels (red, green, blue), each 0–255 (or 0–1, depending on the API). The same orange is rgb(255, 107, 53). Mathematically identical to HEX; just a different notation.
Use it when. You need alpha in modern CSS (rgb(255 107 53 / 0.5)), working with image pixel data, or piping color into a canvas / WebGL API.
HSL — the designer's secret weapon
Hue (0–360°), saturation (0–100%), lightness (0–100%). The same orange ishsl(16, 100%, 60%). The killer feature: tweak one axis at a time. Generating a tint? Raise lightness. Generating a shade? Lower it. Generating a complement? Rotate hue by 180°.
Use it when. Generating palettes algorithmically, creating tint/shade scales, defining hover/active states from a base color.
Caveat. HSL is not perceptually uniform. HSL 50% lightness at yellow looks much brighter than HSL 50% at purple. For perceptually-even scales, use HSLuv or LCH instead.
CMYK — the print reality
Cyan, magenta, yellow, key (black) — each 0–100%. CMYK is a subtractive model used by printers. The hex orange above does not exist in CMYK; the printer picks the closest reproducible value, which is why brand colors often shift between screen and print.
Use it when. Preparing files for print. Otherwise: ignore CMYK in digital work.
Format decision tree
- Web development. HEX for static colors.
hsl()orcolor-mix()when you need to generate variants.rgb()when you need alpha. - Digital design. HEX for handoff. HSL while exploring.
- Print. CMYK, always — and request a proof.
- Brand systems. Specify HEX, RGB, HSL, and CMYK for every brand color. Treat them as one identity in four notations.
The conversions
HEX → RGB
Split the hex into three pairs. Convert each pair from base-16 to base-10. That's it.
#FF6B35
R: FF = 255
G: 6B = 107
B: 35 = 53
→ rgb(255, 107, 53)RGB → HSL
The math is more involved — find max / min channels, compute lightness as the midpoint, compute saturation against that midpoint, compute hue based on which channel is max. Don't write this by hand; every standard library has it. In JavaScript:
import chroma from 'chroma-js';
chroma('#FF6B35').hsl();
// → [16.0, 1.0, 0.6, 1.0] // h, s, l, aTools we recommend
- chroma.js — the practical JS color library. HEX/RGB/HSL/LAB/LCH, mixing, contrast.
- culori — modern, supports OKLCH and the newer CSS color models.
- Our color picker — every format displayed live as you adjust a color.
- Color Picker for VS Code — inline conversion in the editor.
Five mistakes to avoid
1. Starting with RGB for everything
RGB feels safe because it's "native" but it's unreadable in code. Use HEX for static values and HSL when you need to manipulate.
2. "It looks right on my screen"
Monitors lie. Calibrate, or at least sanity-check on a phone, a non-Retina laptop, and in bright sunlight. Your "subtle gray" might be invisible on half the devices.
3. Guessing hex codes by sight
Six digits is too many to eyeball. Use a picker. Use a token. Document the canonical value. #FF6B35 and #FF6C35 are different and your design system will eventually meet both.
4. Assuming colors look the same everywhere
sRGB on a phone is not the same as DCI-P3 on a Mac is not the same as a CMYK print. Define brand colors in every relevant format from the start.
5. Set-and-forget palettes
Browser color management improves every year. Wide-gamut displays are now common. The token system that ignores OKLCH today is the migration you'll pay for next year.