This cheatsheet lists every color notation CSS accepts, with the exact syntax, value ranges and what the browser prints back. It is for developers who copy a color from a design file and need it in another format. The common confusion is alpha: hex puts it in the last two digits, while rgb() and hsl() take a percentage or a number after a slash. Background on the hex form itself is in the Hex color term, and the color space behind most of these formats is sRGB.
| Notation | Example | Components | Gamut |
|---|---|---|---|
| Hex | `#3366cc` | red, green, blue as 2 hex digits each | sRGB |
| `rgb()` | `rgb(51 102 204)` | 0-255 or 0%-100% per channel | sRGB |
| `hsl()` | `hsl(220 60% 50%)` | hue, saturation, lightness | sRGB |
| `hwb()` | `hwb(220 20% 20%)` | hue, whiteness, blackness | sRGB |
| `lab()` | `lab(50% 40 59.5)` | lightness, a axis, b axis | Covers all visible colors |
| `lch()` | `lch(50% 70 40)` | lightness, chroma, hue | Covers all visible colors |
| `oklab()` | `oklab(62% 0.15 0.08)` | lightness, a axis, b axis | Covers all visible colors |
| `oklch()` | `oklch(62% 0.2 29)` | lightness, chroma, hue | Covers all visible colors |
| `color()` | `color(display-p3 1 0 0)` | a named space plus three numbers | Depends on the space |
| `color-mix()` | `color-mix(in srgb, red 50%, blue)` | two colors and a mixing space | Result of the mix |
| Keyword | `tomato` | one of 148 named colors | sRGB |
The syntax comes from CSS Color Module Level 4, which was a W3C Candidate Recommendation Draft dated 30 September 2026 when this sheet was written.
A hex color is # followed by 3, 4, 6 or 8 hex digits. Letter case does not matter.
| Digits | Form | Example | Result in Chromium 153 |
|---|---|---|---|
| 3 | `#rgb` | `#f00` | `rgb(255, 0, 0)` |
| 4 | `#rgba` | `#f008` | `rgba(255, 0, 0, 0.533)` |
| 6 | `#rrggbb` | `#ff0000` | `rgb(255, 0, 0)` |
| 8 | `#rrggbbaa` | `#ff000080` | `rgba(255, 0, 0, 0.5)` |
| 5 or 7 | none | `#12345` | Invalid, the declaration is dropped |
Short forms double each digit, so #f08 is #ff0088. The 4-digit alpha 8 becomes 88, which is 136 of 255 and prints as 0.533, not 0.5.
| Opacity | Hex pair | Opacity | Hex pair |
|---|---|---|---|
| 100% | `ff` | 40% | `66` |
| 90% | `e6` | 30% | `4d` |
| 80% | `cc` | 25% | `40` |
| 75% | `bf` | 20% | `33` |
| 70% | `b3` | 10% | `1a` |
| 60% | `99` | 5% | `0d` |
| 50% | `80` | 0% | `00` |
| Function | Channel 1 | Channel 2 | Channel 3 | Alpha |
|---|---|---|---|---|
| `rgb()` | 0-255 or 0%-100% | same | same | 0-1 or 0%-100% |
| `hsl()` | hue in degrees | saturation % | lightness % | 0-1 or 0%-100% |
| `hwb()` | hue in degrees | whiteness % | blackness % | 0-1 or 0%-100% |
| `lab()` | L 0%-100% | a, about -125 to 125 | b, about -125 to 125 | 0-1 or 0%-100% |
| `oklch()` | L 0-1 or 0%-100% | chroma, about 0 to 0.4 | hue in degrees | 0-1 or 0%-100% |
The a, b and chroma bounds for Lab-type spaces are not hard limits in the spec; they describe where real colors sit.
| Keyword | Space |
|---|---|
| `srgb` | sRGB with gamma encoding |
| `srgb-linear` | sRGB without gamma |
| `display-p3` | Display P3, wider than sRGB |
| `a98-rgb` | Adobe RGB (1998) |
| `prophoto-rgb` | ProPhoto RGB |
| `rec2020` | ITU-R BT.2020-2 |
| `xyz`, `xyz-d50`, `xyz-d65` | CIE XYZ, with `xyz` meaning D65 |
| Keyword | Meaning |
|---|---|
| `transparent` | Computes to `rgba(0, 0, 0, 0)` |
| `currentcolor` | The element's own `color` value |
| `none` | A missing component inside `hsl()`, `lab()`, `oklch()` and similar |
.a { color: #3366cc; }
.b { color: rgb(51 102 204); }
.c { color: hsl(220 60% 50%); }
.d { color: hwb(220 20% 20%); }
All four describe the same sRGB color. A script that converted #3366cc gave rgb 51 102 204, hsl(220 60% 50%) and hwb(220 20% 20%). Pick hsl() when you want to adjust lightness by hand.
const hex = '#3366cc';
const [r, g, b] = [1, 3, 5].map(i => parseInt(hex.slice(i, i + 2), 16));
const R = r / 255, G = g / 255, B = b / 255;
const max = Math.max(R, G, B), min = Math.min(R, G, B), d = max - min;
const l = (max + min) / 2;
const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
let h = max === R ? ((G - B) / d) % 6 : max === G ? (B - R) / d + 2 : (R - G) / d + 4;
h = (h * 60 + 360) % 360;
console.log('hsl(' + Math.round(h) + ' ' + Math.round(s * 100) + '% ' + Math.round(l * 100) + '%)');
console.log('hwb(' + Math.round(h) + ' ' + Math.round(min * 100) + '% ' + Math.round((1 - max) * 100) + '%)');
Output:
hsl(220 60% 50%)
hwb(220 20% 20%)
Whiteness is the smallest channel and blackness is one minus the largest. The Color Converter does the same conversion between HEX, RGB, HSL, HSV and CMYK without code.
.a { color: #ff000080; }
.b { color: rgb(255 0 0 / 50%); }
.c { color: rgba(255, 0, 0, .5); }
Chromium 153 serialized all three as rgba(255, 0, 0, 0.5). Use the slash form in new code and the comma form only when you must support old parsers.
.mix { color: color-mix(in srgb, red 50%, blue); }
Computed value in Chromium 153:
color(srgb 0.5 0 0.5)
The in keyword picks the space where the mix happens, so the same two colors give a different result in oklch than in srgb.
.half { color: rgb(from #336699 r g b / 50%); }
Computed value in Chromium 153:
color(srgb 0.2 0.4 0.6 / 0.5)
The from keyword exposes the source color's channels as r, g and b, here to set half opacity without changing the color.
.hero {
background: rgb(255 0 0);
background: color(display-p3 1 0 0);
}
A browser that does not understand color() drops the second line and keeps the sRGB fallback. Chromium 153 kept color(display-p3 1 0 0).
#f008 is 136 out of 255, which is 0.533, not 0.5. Write #ff000080 for exactly half.rgb(255, 0, 0 / .5) is invalid and Chromium 153 ignored the declaration. Use all commas with rgba(), or all spaces with a slash.rgb(300 0 0) is accepted and clamped, and Chromium 153 returned rgb(255, 0, 0).#12345 is dropped, so the property falls back to the inherited or default value, which can turn text black.tomato computes to rgb(255, 99, 71) and hsl(120deg 100% 25%) to rgb(0, 128, 0). Compare colors by their computed form, not by string.hsl() lightness can look very different in brightness. oklch() lightness tracks perception much better, which matters for contrast.rgb() and hsl() still accept commas, but the legacy form cannot use none or mix numbers and percentages.color(display-p3 …) or oklch().