The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
Use modern RGB syntax.swatch { color: rgb(34 70 160 / 85%); }View examples
Use cylindrical sRGB.swatch { color: hsl(220 65% 42% / .85); }View examples
Use perceptual polar color.swatch { color: oklch(62% .18 255); }View examples
Supply a Display P3 color.swatch { color: #0b63ce; color: color(display-p3 0.05 0.38 0.86); }View examples
Gate wide-gamut syntax@supports (color: color(display-p3 1 0 0)) { .brand { color: color(display-p3 .1 .5 .9); }; }View examples
Check output gamut@media (color-gamut: p3) { .hero { --accent: color(display-p3 .1 .55 .9); }; }View examples
Mix in OKLab.border { color: color-mix(in oklab, var(--accent) 35%, transparent); }View examples
Create a tint.panel { background: color-mix(in oklch, var(--accent) 15%, white); }View examples
Choose a hue path.spectrum { color: color-mix(in oklch longer hue, red, blue); }View examples
Adjust an origin color.hover { color: oklch(from var(--accent) calc(l + .08) c h); }View examples
Change only alpha.overlay { background: rgb(from var(--accent) r g b / 35%); }View examples
Preserve a missing component.variant { color: oklch(from var(--accent) l c none); }View examples
Choose by used color scheme:root { color-scheme: light dark; --surface: light-dark(#fff, #111827); }View examples
Adapt to forced colors.button { color: ButtonText; background: ButtonFace; border-color: ButtonText; }View examples
Remove decorative imagery@media (forced-colors: active) { .badge { background-image: none; border: 1px solid CanvasText; }; }View examples
Interpolate a gradient in OKLab.hero { background: linear-gradient(in oklab, #06b6d4, #7c3aed); }View examples
Choose a gradient hue path.wheel { background: linear-gradient(in oklch longer hue, red, blue); }View examples
Disable nonessential color motion@media (prefers-reduced-motion: reduce) { .pulse { animation: none; }; }View examples
Pair color with a text cue<p class="status" role="status"><span aria-hidden="true">✓</span> Backup complete</p>View examples

Modern CSS can express colors in device-independent and wide-gamut spaces, derive variants from tokens, and choose interpolation rules explicitly. Those powers do not guarantee contrast, gamut availability, or uniform browser support. This guide builds a resilient sRGB baseline, progressively enhances perceptual color, and separates computed color math from accessibility decisions.

Step by step

Detailed examples

01

Choose a space for the task

rgb() and hsl() produce sRGB colors; Lab and LCH are based on CIE Lab, while OKLab and OKLCH provide a perceptual model tuned for screen work. Polar spaces use hue angles and chroma; rectangular spaces use opponent axes. Equal numeric changes are not guarantees of equal contrast. Alpha controls compositing, not lightness, and transparent colors reveal whatever is behind them.

Layer perceptual color over sRGB
:root { --accent: #2764d8; --accent: oklch(58% .19 255); }
.button { background: var(--accent); color: white; }
Back to quick reference ↑
02

Keep an sRGB baseline before wide gamut

color() can address predefined spaces such as display-p3, rec2020, and srgb-linear. A syntactically valid color may still be outside the output device gamut and is gamut-mapped for display. Put an sRGB declaration first, optionally gate the enhancement with @supports, and use color-gamut only when device capability should influence the design. Screenshots and automated visual tests may run in sRGB even when production hardware is wider.

Progressive P3 accent
.brand { color: rgb(0 101 210); }
@supports (color: color(display-p3 0 0 0)) {
  .brand { color: color(display-p3 0 .39 .88); }
}
Back to quick reference ↑
03

Specify the interpolation space explicitly

color-mix() combines colors in a declared interpolation method; the default space is OKLab when omitted, but explicit is clearer. Percentages are normalized under defined rules, and a total below 100% introduces alpha. Polar spaces accept shorter, longer, increasing, or decreasing hue interpolation. Mixing with transparent can change color channels differently from merely changing alpha, so inspect the composited result on actual surfaces.

Derived token scale in OKLCH
:root {
  --accent: oklch(58% .19 255);
  --accent-soft: color-mix(in oklch, var(--accent) 18%, white);
  --accent-border: color-mix(in oklab, var(--accent) 45%, transparent);
}
Back to quick reference ↑
04

Derive variants from an origin without string tricks

Relative color syntax begins with from <color>, converts the origin into the target function space, and exposes numeric channel keywords plus alpha. Components can be copied or used inside math. They are numbers in defined scales, so percentage assumptions do not transfer magically between channels. Provide precomputed fallback tokens because support and serialization vary, and clamp deliberate calculations when values could exceed a useful design range.

Fallback then relative hover color
.link { --hover: #1746a2; --hover: oklch(from var(--accent) clamp(0, calc(l - .1), 1) c h); }
.link:hover { color: var(--hover); }
Back to quick reference ↑
05

Negotiate schemes without promising contrast

light-dark() chooses according to the used color scheme and requires the page or element to declare supported schemes with color-scheme. System colors adapt to forced palettes. Neither light-dark(), OKLCH lightness, color-mix(), nor contrast-color() by itself proves WCAG contrast for arbitrary text sizes and backgrounds. Validate final composited pairs, including hover, focus, disabled, visited, dark, high-contrast, and translucent states. Avoid forced-color-adjust:none unless you fully replace the lost adaptation.

Scheme-aware surface with forced-color resilience
:root { color-scheme: light dark; --surface: light-dark(#fff,#111827); --text: light-dark(#172033,#f8fafc); }
.card { color: var(--text); background: var(--surface); border: 1px solid currentColor; }
Back to quick reference ↑
06

Control interpolation and motion independently

Gradients accept an interpolation color space and optional hue method, while color-mix() carries its own explicit interpolation method. Transitions and animations otherwise use the interpolation rules defined for the animated property. Different spaces can produce visibly different midpoints and gamut excursions. Color changes still can flash or distract; respect prefers-reduced-motion for nonessential repeating effects, avoid rapid luminance changes, and animate paint-heavy full-screen gradients sparingly.

Perceptual gradient with a static reduced-motion state
.hero { background: linear-gradient(90deg in oklab,#06b6d4,#7c3aed); animation: hue 6s alternate infinite; }
@keyframes hue { to { filter: hue-rotate(25deg); } }
@media (prefers-reduced-motion: reduce) { .hero { animation: none; } }
Back to quick reference ↑
07

Test computed colors on real output conditions

Cascade a conservative value before every new syntax whose absence would hide content. @supports detects parsing, not gamut, contrast, or correct appearance. Test sRGB and P3 displays, light and dark schemes, forced colors, increased contrast, print, transparency over varied surfaces, and disabled custom properties. Avoid encoding status by color alone; pair it with text, icons, patterns, or shape. Use currentColor to keep borders and icons synchronized with accessible foreground choices.

Status uses text, shape, and adaptable color
<p class="status" role="status"><span aria-hidden="true">✓</span> Backup complete</p>
Visible without color alone
.status { color: #176b3a; color: oklch(47% .13 150); border: 2px solid currentColor; border-radius: .5rem; padding: .75rem; }
Back to quick reference ↑

Local code tester

Compare color interpolation spaces

Choose sRGB, OKLab, or OKLCH to compare gradient midpoints and derived surfaces while text and borders retain explicit fallbacks.

Runs in your browser
Preview

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. CSS Working GroupCSS Color Module Level 4drafts.csswg.org
  2. CSS Working GroupCSS Color Module Level 5drafts.csswg.org
  3. CSS Working GroupCSS Color Adjustment Module Level 1drafts.csswg.org
  4. CSS Working GroupMedia Queries Level 5drafts.csswg.org
  5. MDN Web DocsCSS colorsdeveloper.mozilla.org

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback