CSS color recipe

Relative colors Hover, disabled and chip colors derived from one brand color

Relative color syntax takes a color apart into its channels and lets you change any of them: oklch(from var(--brand) calc(l - 0.08) c h) is the brand, 8 points darker. States stay tied to the brand without a second palette.

See it run
Baseline
Newly available
First versions
Chrome 125 · Firefox 128 · Safari 18
Tested
3 of 3 engines

Live example

The recipe, running

Left: the CSS below, as your browser runs it. Right: the same CSS as a browser without the feature reads it, so you see exactly what the fallback gives.

Turn on JavaScript to see whether your browser supports it; the examples work either way.

As written, in your browser
In a browser without it

The CSS

Copy it as it is

This is the exact CSS the example runs. Fallbacks come first; the modern values follow, so each browser keeps the last line it understands.

relative-color.css

:root { --brand: #3959DA; }

.button { padding: 10px 18px; border: 0; border-radius: 8px; background: var(--brand); color: #ffffff; font: inherit; }
.button:hover, .button.is-hover { background: #273FBE; }
.button:disabled { background: rgb(57 89 218 / 0.45); }
.chip { padding: 4px 12px; border-radius: 999px; background: #E9EEFC; color: #243B9C; }

@supports (color: oklch(from red l c h)) {
  .button:hover, .button.is-hover { background: oklch(from var(--brand) calc(l - 0.08) c h); }
  .button:disabled { background: oklch(from var(--brand) l c h / 0.45); }
  .chip {
    background: oklch(from var(--brand) 0.95 calc(c * 0.1) h);
    color: oklch(from var(--brand) 0.4 calc(c * 0.8) h);
  }
}

How it works

What each part does

  1. Channels are numbers. Inside oklch(from …), l, c and h are plain numbers, so calc() can shift them and / 0.45 sets the alpha.

  2. The fallbacks are those results. Each hex is the derived OKLCH color converted to sRGB; every one is inside sRGB, so it matches.

  3. Safari 18 or later. Earlier Safari versions read relative colors with an older version of the syntax, which is why the support table starts there.

Browser support

Where it runs

First version of each browser with the feature, from the web-features project and MDN’s browser-compat-data. “No” means not supported yet.

  • Relative colorsNewly availableBaseline newly available since 16 September 2024: every core browser has it, but older versions in use may not.
First supporting version by browser
BrowserRelative colors
Chrome125
Chrome for Android125
Edge125
Firefox128
Firefox for Android128
Safari18
Safari on iOS18

Support reviewed on against web-features 98723fd and browser-compat-data 3b28abe.

Tested

Tested in three engines

Engines this recipe was run in
EngineVersionSupportedAs writtenFallback
Chromium147.0.7727.15YesPassPass
Firefox148.0.2YesPassPass
WebKit26.4YesPassPass

Run on in Chromium 147.0.7727.15, Firefox 148.0.2 and WebKit 26.4, with Playwright.

Accessibility

Measured, not assumed

White on the hover color measures 8.27:1; the chip’s text measures 8.30:1 on its background.

  • 8.27:1AAA#FFFFFF / #273FBE
  • 8.30:1AAA#243B9C / #E9EEFC

References

Go to the source