HEX is just RGB
#RRGGBB packs red, green, blue as hex (0–255). #ff0000 is pure red. They are just different notations for the same data.
HSL is better for tweaking
HSL = hue / saturation / lightness. "make it lighter" or "shift the hue" changes one number; in RGB you must move three.
Alpha
Add an 8th digit or use rgba() / hsla(): in #rrggbbaa, aa is alpha (00 transparent, ff opaque).
Two pitfalls
- Different color spaces: sRGB vs P3 screens differ; cross-device you get color shift;
- Letter case: HEX is case-insensitive, but don't mix cases or string compares fail.
Try it
Convert formats: Color converter.
Real-world cases: three colour pitfalls
- Colour shift between mockup and page: the design uses Display P3 while the web renders sRGB, so the same value looks darker. Pick colours in sRGB for cross-device consistency.
- Forgetting alpha and blocking content: you meant semi-transparent but used opaque
#rrggbb, hiding what is underneath. Transparency needs 8-digit HEX orrgba(). - Writing HSL lightness as 0–255: HSL saturation and lightness are percentages; 0–255 is out of range and gets clamped, so the colour is simply wrong.
FAQ
Does HEX to RGB lose fidelity? No — they are different notations for the same data and convert losslessly. Why is HSL handy for tweaking? "Make it lighter" or "shift the hue" maps to a single number, versus moving three channels in RGB. Is #f00 the same as #ff0000? Yes, the three-digit form duplicates each nibble. How do I keep dark mode readable? Compute WCAG contrast: at least 4.5:1 for body text rather than eyeballing it.
Accessible colour in practice
Colour must be readable, not just attractive. A workable order:
- Build neutral ramps first: fix the hue in HSL and vary only lightness to get 50–900 steps for backgrounds, borders and secondary text;
- Then brand and status colours: one base each for primary, success, warning and error, plus hover (about 8% darker) and active (8% again);
- Verify contrast: at least
4.5:1for body text on its background,3:1for large text and icons; - Never encode meaning in colour alone: error states also need text or an icon for colour-blind users.
Common misconceptions
- Darkening by subtraction: dropping 20 from each RGB channel also desaturates and greys the colour — lower L in HSL instead;
- Ignoring dark mode: you cannot simply swap foreground and background; brand colours usually need lightening to keep contrast;
- Treating alpha as "a lighter brand colour": translucency over a dark background shifts hue — use a solid colour and tune it;
- Hard-coded hex values: scattered literals make theming painful; centralise them as design tokens.
Order of operations for cross-device consistency
First confirm the mockup's colour space (sRGB or P3), then whether your screenshot tool applies colour management, and only then compare values. Most "colour shift" reports come from the capture chain, not the page.
Design token suggestions
- Semantic names: use
--color-dangerrather than--color-redso theming needs no component edits; - Expose a limited ramp: 50–900 is plenty; thirty-seven near-identical greys cause visual drift;
- Dark values too: every semantic colour needs a dark-mode value rather than a filter or opacity hack;
- One source, many formats: keep CSS variables, JS constants and design-tool variables in sync.
Colour and maintainability
Do not duplicate a hex value across stylesheets, chart config and code constants. Centralise them as design tokens and export from there, or changing one brand colour means editing five or six files — miss one and you get two subtly different blues.
Print versus screen
Screens are additive (RGB), print is subtractive (CMYK), so the same value prints noticeably darker. When physical output is involved, proof in CMYK or Pantone from the design stage rather than handing web values to the printer — otherwise it looks great on screen and muddy on paper.