Table of Contents
Colors in CSS are not just decoration — they are a technical decision with real consequences for maintainability, accessibility, and design consistency. A hex code, an RGB triple, an HSL declaration, and an OKLCH value can all describe the exact same perceptual color, yet each format has different strengths, different readability, and different browser support characteristics.
This guide covers every color format you will encounter in modern CSS: the six-digit hex and its shorthand variants, the classic rgb() and rgba() functions, the human-friendlier hsl() and hsla(), the newer hwb(), the perceptually uniform oklch() and oklab(), CSS named colors, and the CMYK model used in print. For each format, you will understand not just the syntax but the mental model — which makes it easy to pick the right format for the right job, and to convert confidently when you need to.
All conversion tools referenced here run entirely in your browser. No files are uploaded. No data is collected.
Hex Colors: The Universal Starting Point
Hex color notation is the most widely recognised color format in web development, and almost certainly the one you learned first. A hex color encodes red, green, and blue channels as two-digit hexadecimal numbers concatenated into a six-character string preceded by a hash sign.
#RRGGBB #FF5733 → R=255, G=87, B=51
Each pair ranges from 00 (0 in decimal, channel off) to FF (255 in decimal, channel fully on). This gives 256 × 256 × 256 = 16,777,216 possible colors.
Shorthand hex (#RGB) is valid when both digits in each channel pair are identical. #FF5533 can be written as #F53, which expands to #FF5533. This only applies when all three pairs consist of repeated digits.
8-digit hex (#RRGGBBAA) adds an alpha transparency channel using the same hexadecimal encoding. #FF573380 is the same red at 50% opacity (0x80 = 128 ≈ 50% of 255). Similarly, #RGBA is the 4-digit shorthand. This format is supported in all modern browsers.
When to use hex:
- Copying a brand color out of a design system or design file — most tools export hex by default
- Working in codebases that already use hex consistently
- When you want the most compact representation for static color values
Limitations of hex:
- Not human-readable:
#3A86FFtells you almost nothing about the color without a picker - Hard to manipulate programmatically: darkening a hex color by 10% requires channel arithmetic
- Alpha is appended as an extra pair, which is not intuitive
RGB and RGBA: Numeric Channels
The rgb() function is the functional equivalent of hex — it specifies the same three red, green, and blue channels, but as decimal integers (0–255) or percentages (0%–100%).
rgb(255, 87, 51) /* same as #FF5733 */ rgb(100%, 34%, 20%) /* equivalent percentage form */ rgba(255, 87, 51, 0.5) /* 50% opacity */
Modern CSS (Level 4 specification) allows the space-separated syntax without commas and accepts none as a channel value:
rgb(255 87 51) rgb(255 87 51 / 50%) /* modern form of rgba */
Alpha in RGB: The fourth argument (in rgba() or after the slash in the modern syntax) accepts a number from 0 (fully transparent) to 1 (fully opaque), or a percentage.
When to use RGB:
- When your design tools or color references give you decimal channel values
- When doing color arithmetic in CSS or JavaScript — adding/subtracting channel values
- Passing color values to Canvas API, WebGL, or image processing libraries that expect
[r, g, b]arrays
Limitations of RGB:
- Still not perceptually intuitive: similar to hex, the three numbers do not correspond to how humans describe colors (lightness, saturation, hue)
- Manipulating colors by "feel" (make this darker, more saturated) requires knowing which channels to adjust
HSL and HSLA: The Designer's Color Model
HSL stands for Hue, Saturation, and Lightness. It was introduced to CSS specifically because it maps more naturally to how designers and artists think about color.
hsl(14, 100%, 60%) /* an orange-red */ hsl(14deg, 100%, 60%) /* hue can be written with deg unit */ hsla(14, 100%, 60%, 0.5) /* 50% opacity */ hsl(14 100% 60% / 50%) /* modern slash syntax */
Hue is an angle on the color wheel (0–360°):
- 0° / 360°: Red
- 30°: Orange
- 60°: Yellow
- 120°: Green
- 180°: Cyan
- 240°: Blue
- 270°: Violet
- 300°: Magenta
Saturation controls color intensity: 0% is grey (no color), 100% is fully vivid.
Lightness controls luminance: 0% is black, 50% is the "pure" color, 100% is white.
Why HSL is powerful for CSS authoring:
Generating color variations with HSL is trivial. To create a 10-step lightness scale for a single hue, you only change the third value:
--blue-100: hsl(220, 90%, 95%); --blue-200: hsl(220, 90%, 87%); --blue-500: hsl(220, 90%, 50%); --blue-900: hsl(220, 90%, 15%);
To create a hover state that is 10% darker, subtract 10 from the L value. To create a muted variant, drop saturation to 30%. This arithmetic is impossible with hex.
HSL's main limitation: HSL is not perceptually uniform. Two colors at the same stated lightness level (e.g., hsl(120, 100%, 50%) green vs hsl(240, 100%, 50%) blue) look dramatically different in brightness to the human eye. This matters for accessibility — HSL lightness alone is not a reliable guide to contrast ratios.
OKLCH and OKLAB: Perceptually Uniform Modern Colors
OKLCH and OKLAB are the modern replacements for HSL and Lab, introduced in the CSS Color Level 4 specification and supported in all major browsers since 2023.
oklch(70% 0.15 250) /* L=70%, C=0.15, H=250° */ oklab(0.70 -0.05 -0.12) /* L=70%, a=-0.05, b=-0.12 */
OKLCH channels:
- L (Lightness): 0 (black) to 1 or 0%–100%. This lightness is perceptually uniform —
oklch(60% …)looks equally bright regardless of hue. - C (Chroma): 0 (grey) to ~0.4 (max vivid). Not a percentage — chroma scales differ by hue.
- H (Hue): 0–360° angle, same convention as HSL.
Why perceptual uniformity matters:
When you create a theme and need all your accent colors to feel equally prominent, OKLCH guarantees that. A green accent and a blue accent at oklch(65% 0.18 H) will appear equally bright. The same statement in HSL is false.
P3 and wide-gamut colors:
OKLCH can express colors outside the sRGB gamut — vivid colors that modern displays (especially Apple's Retina/P3 displays) can render but that hex and HSL cannot represent. These out-of-gamut colors are simply clamped on displays that cannot show them.
/* A vivid green only possible in Display P3 */ oklch(75% 0.30 145)
When to use OKLCH:
- Building a design token system from scratch in 2025+
- Generating color scales programmatically (lightness steps are perceptually even)
- Targeting modern browsers where you want the widest possible color gamut
- Any context where accessibility (contrast) is being designed systematically
Browser support: Chrome 111+, Firefox 113+, Safari 15.4+ (with color(display-p3 …) syntax), Edge 111+.
HWB: Hue, Whiteness, Blackness
HWB is a CSS Color Level 4 format that expresses color as a hue plus amounts of white and black mixed in. It is more intuitive than HSL for tinting and shading.
hwb(14 0% 0%) /* pure hue, no white or black added */ hwb(14 40% 0%) /* same hue with 40% white mixed in — a tint */ hwb(14 0% 40%) /* same hue with 40% black mixed in — a shade */ hwb(14 30% 30%) /* balanced grey-shifted mid tone */
When whiteness + blackness exceed 100%, both are proportionally scaled to sum to 100%, and the result is a pure grey.
HWB is particularly readable for generating tints and shades: to lighten a color, increase the whiteness. To darken it, increase the blackness. No lightness math required.
Browser support: All major browsers since 2022.
CSS Named Colors
CSS defines 148 named colors, from aliceblue and antiquewhite to yellowgreen. These are case-insensitive and map to specific hex values.
The named colors fall into several groups:
- Basic colors:
red,green,blue,white,black,yellow,cyan,magenta - Extended X11 colors:
cornflowerblue(#6495ED),mediumseagreen(#3CB371),tomato(#FF6347) - Special values:
transparent(fully transparent black),currentColor(inherits the element'scolorproperty),inherit,initial,unset
Named colors are useful for quick prototyping, debugging, and cases where readability matters more than precision. They are not suitable for design systems because there is no predictable relationship between names — lightblue is not a predictable tint of blue.
CMYK: Print Colors and When You Need to Convert
CMYK (Cyan, Magenta, Yellow, Key/Black) is the standard color model for print production. It is a subtractive model: inks absorb (subtract) light, so combining all four at 100% produces black.
CSS does not natively support CMYK. If you receive a brand color defined as C:12 M:85 Y:90 K:3 (a warm red), you must convert it to hex/RGB for use on the web.
CMYK to RGB conversion:
R = 255 × (1 - C/100) × (1 - K/100) G = 255 × (1 - M/100) × (1 - K/100) B = 255 × (1 - Y/100) × (1 - K/100)
For C:12 M:85 Y:90 K:3:
- R = 255 × (1 - 0.12) × (1 - 0.03) = 255 × 0.88 × 0.97 ≈ 218
- G = 255 × (1 - 0.85) × (1 - 0.03) = 255 × 0.15 × 0.97 ≈ 37
- B = 255 × (1 - 0.90) × (1 - 0.03) = 255 × 0.10 × 0.97 ≈ 25
Result: rgb(218, 37, 25) → #DA2519
Important caveat: CMYK and RGB are different color spaces, and the conversion above is a mathematical approximation. Professional print work uses ICC color profiles for accurate gamut mapping. For web use, the formula above is sufficient for matching a brand color's intent.
Convert CMYK to RGB— Enter CMYK values, get hex + CSS output instantlyColor Format Comparison: When to Use What
Here is a practical decision framework:
| Situation | Best format |
|---|---|
| Copying from Figma or Sketch | Hex (#RRGGBB) |
| CSS custom property color scales | HSL or OKLCH |
| Accessibility-driven design system | OKLCH |
| Canvas API / WebGL | RGB float arrays or rgb() |
| Print brand color → web | CMYK → RGB conversion |
| Quick prototype / debugging | Named colors |
| Wide-gamut Display P3 colors | OKLCH |
| Legacy browser support (IE11) | Hex or rgb() only |
For new design systems in 2025, the recommended stack is:
1. Design in OKLCH for perceptual uniformity and scale generation
2. Export to hex or hsl() for compatibility with older tooling
3. Use @supports (color: oklch(0 0 0))) for progressive enhancement if targeting older browsers
How CSS Parses Color Values
Understanding CSS color parsing prevents bugs. The CSS parser resolves color values at computed value time — before layout and paint. All color formats ultimately resolve to the same internal representation (an sRGB or wider-gamut triplet plus alpha).
Key parsing rules:
- Hex colors are case-insensitive:
#FF5733=#ff5733=#fF5733 rgb()andhsl()with the comma syntax (Level 3) and space-slash syntax (Level 4) are both valid in modern browsers- Out-of-range values are clamped:
rgb(300, 87, 51)clamps R to 255 rgba()andhsla()are aliases —rgb()now accepts a fourth alpha argument in all modern browserscolor-mix()(CSS Level 5) mixes two colors in a specified color space:color-mix(in oklch, #3A86FF 70%, white)
The `color()` function allows specifying colors in explicit color spaces:
color(display-p3 0.9 0.2 0.1) /* a vivid red in Display P3 */ color(srgb 1.0 0.34 0.2) /* sRGB explicit */ color(xyz-d65 0.41 0.21 0.02) /* CIE XYZ */
Frequently Asked Questions
Is hex or RGB better for CSS?
What is the difference between HSL and HSB/HSV?
Can I use OKLCH in production today (2025)?
Why does my HSL color look different from what I expected?
How do I convert a CMYK brand color to CSS hex?
What are CSS color levels 4 and 5?
Summary
Color formats in CSS are more varied than most developers realize, and the right choice depends on your context. Hex is the default workhorse for design handoff. HSL is the practical choice for authoring maintainable color scales. OKLCH is the future: perceptually uniform, gamut-expansive, and now broadly supported.
The conversion tools at LevnTools cover every direction — hex to RGB, RGB to hex, HSL to hex, CMYK to RGB, and more — all client-side with instant output you can copy directly into your stylesheets. No account required.