For thirty years, "a color" on the web meant #RRGGBB in sRGB, and the only debate was over how many decimal places rgba() needed. CSS Color Module Level 4 changed both halves of that sentence: there are now several authoring formats with real differences, and the underlying gamut can be wider than sRGB. This guide covers the formats you will actually use in 2026, what each one is good at, and why design system teams have been migrating tokens to OKLCH.
1. HEX: the universal shorthand
HEX notation — #RRGGBB or #RRGGBBAA for alpha — is a compact way to write an sRGB color as three (or four) bytes. CSS also accepts the three- and four-digit shorthand #RGB / #RGBA, which expands by repeating each digit (#abc becomes #aabbcc). HEX is the lingua franca of design tools, ecosystems like Figma, and command-line snippets — but it is not a separate color space. Every HEX value is just sRGB written in base 16.
Limitations to remember: HEX cannot express colors outside sRGB, cannot represent transparency in fewer than 8 hex digits, and is opaque to humans (you cannot tell at a glance that #7c3aed is a vibrant violet). For raw values in code, fine. For design tokens you will edit and remix, less so.
2. RGB(A): the same value, more readable
rgb() and rgba() express the same sRGB triplet as HEX, just in decimal. CSS Color Module Level 4 modernised the syntax — commas are no longer required and alpha is a slash-separated component — so rgb(124 58 237 / 0.8) is the canonical 2026 form. The old rgba(124, 58, 237, 0.8) still works for compatibility.
Use RGB when you are pulling channel values out of a camera, image, or sensor — anywhere the input is naturally per-channel. For palette authoring, the next two formats give you a more useful axis to work along.
3. HSL and HWB: friendlier authoring, not perceptual
hsl() exposes hue (0–360 degrees on the color wheel), saturation, and lightness. It is a transformation of sRGB, not a separate color space, and it gives authors a coordinate system that aligns with intuition: shift the hue to recolor a button, lower the saturation to mute it, raise the lightness for a hover state. HWB (hue, whiteness, blackness) is the same idea with a different lightness/saturation parameterisation, intended to feel more like mixing paint.
The catch is that HSL's lightness is not perceptually uniform. hsl(60 100% 50%) is yellow at 50% lightness, and hsl(240 100% 50%) is blue at 50% lightness, but the yellow visibly appears lighter. Generating a 5-step lightness ramp by stepping the L coordinate produces ramps where yellows blow out and blues stay too dark. This is why HSL-based design tokens always need manual tuning.
4. LCH and OKLCH: perceptually uniform color
CIE LCH is built on the CIELAB color space, which was designed to approximate human perception: equal numerical changes in L correspond to roughly equal perceived changes in lightness. lch() exposes that as lightness, chroma (analogous to saturation), and hue. CSS Color Module Level 4 added it directly, and browsers implement gamut mapping to fit the chosen display.
OKLCH is the version most engineers want. Björn Ottosson's 2020 paper introduced the OKLab color space — a refinement of CIELAB with better hue uniformity, especially around blues. oklch() wraps OKLab in the same lightness/chroma/hue interface as lch():
oklch(70% 0.2 250)
Both have lightness 70% and chroma 0.2, differing only in hue. They render at noticeably similar perceived brightness — exactly what HSL fails at. This is why design system teams have been migrating: a single OKLCH token can produce a five-step lightness ramp that looks consistent across every hue.
5. Color spaces: sRGB, P3, Rec2020
All of the formats above are color models — ways of describing a color. The color space is the gamut the model maps onto. sRGB is the default for the web and roughly matches the colors a 1996 CRT could display. Display P3 is about 25% wider, the default on most modern Apple hardware and increasingly on Android. Rec.2020 is wider still and used in HDR video.
CSS Color Module Level 4 added a generic color() function that lets you author directly in any specified color space:
color(display-p3 1 0 0)
color(rec2020 1 0 0)
Each is a different shade of red because each declares its components in a different gamut. Use this when you have wide-gamut source assets (camera RAW, HDR photography) and want them to display in their native gamut where supported, falling back to sRGB elsewhere.
6. Why OKLCH wins for design tokens
Three concrete advantages show up the moment you try to scale a color system:
- Smooth gradients. A linear interpolation between two OKLCH colors stays roughly the perceived "same brightness" throughout. The same interpolation in sRGB or HSL passes through muddy intermediate values.
- Predictable accessibility. Because OKLCH lightness aligns with perception, a foreground/background pair with a fixed L difference produces consistent contrast across hues.
- Programmatic palettes. Generating a 5-step ramp by stepping L from 95 to 25, holding chroma and hue constant, produces visibly even steps for every hue. This is the property that makes OKLCH worth the migration.
7. Decision tree: which format should you use?
- One-off color in a CSS rule → HEX. Universal, compact, fine.
- Design tokens, palettes, programmatic ramps → OKLCH. Generate HEX at build time for legacy consumers.
- Wide-gamut imagery, HDR →
color(display-p3 ...)orcolor(rec2020 ...)with sRGB fallback. - Per-channel processing (camera, sensor, image pipeline) →
rgb()with floats. - Quick hue shifts in code → HSL is still readable, but verify perceived contrast manually.
Convert between color formats
DevToolNow's Color Converter takes any HEX, RGB, HSL, or OKLCH input and emits all four formats with live previews. Useful for building OKLCH tokens against existing HEX values.
Open Color Converter →Frequently asked questions
Q. Is OKLCH supported well enough to ship in 2026?
A. Yes. OKLCH shipped in Safari 15.4 (March 2022), Chrome 111 (March 2023), and Firefox 113 (May 2023). By 2026 it is in all evergreen browsers with three-plus years of stable history. The remaining concern is older corporate environments stuck on a non-evergreen browser; for those you provide a sRGB fallback with the @supports rule or a sass/postcss color-mix step.
Q. Why is HSL not perceptually uniform?
A. HSL was designed in the 1970s for ease of authoring, not for perceptual accuracy. Its lightness coordinate is a simple linear function over the RGB channels, which means a yellow at L=70% looks dramatically brighter than a blue at L=70%. Color palettes built by varying HSL lightness end up with uneven contrast steps. OKLCH and CIE LCH fix this by using a lightness scale that approximates human perception.
Q. Should I still use HEX in my design tokens?
A. HEX is fine as a shorthand for sRGB color in code, and tooling support is universal. But if you generate variations programmatically (lighter / darker / accessible-contrast), authoring tokens in OKLCH and converting to HEX at build time gives you visibly more even results. Many design systems now store the canonical token in OKLCH and emit HEX only for legacy consumers.
Q. What is the difference between Display P3 and sRGB?
A. sRGB is the color space the web was standardised on — roughly the gamut of 1990s CRT monitors. Display P3 is wider, originally from Apple devices, and now standard on most modern phones and laptops. Rec.2020 is wider still, used in 4K HDR video. CSS Color Module Level 4 lets you author colors directly in any of these spaces with the color() function: color(display-p3 1 0 0) is a more saturated red than the sRGB red.
Q. Does OKLCH always produce visible colors?
A. No. OKLCH is a color model, not a gamut. You can specify oklch values that fall outside any displayable color space, in which case the browser performs gamut mapping to fit the destination display's gamut. CSS Color Module Level 4 specifies the algorithm. In practice, sticking to chroma values around 0.15 or below keeps you safely inside sRGB; chroma 0.2+ enters P3-only territory.
References
- W3C — CSS Color Module Level 4
- Björn Ottosson — A perceptual color space for image processing (OKLab/OKLCH, 2020)
- MDN Web Docs — <color> reference, oklch(), color()
- ITU-R BT.2020 — Parameter values for ultra-high definition television systems
- Apple — Display P3 Color Space reference
Note: Color appearance depends on the user's display and the page's color management. Always test wide-gamut output on hardware that supports the target gamut before relying on it for brand-critical color.
About the DevToolNow Editorial Team
DevToolNow's editorial team is made up of working software developers who use these tools every day. Every guide is reviewed against primary sources — IETF RFCs, W3C/WHATWG specifications, MDN Web Docs, and project repositories on GitHub — before publication. We update articles when standards change so the guidance stays current.
Sources we cite: IETF RFCs · MDN Web Docs · WHATWG · ECMAScript spec · Official project READMEs on GitHub