CSS relative color syntax

Igor6.1.2026

CSS has introduced a lot of nice features last couple of years. One of them is the relative color syntax, where you can split a color in different channels and adjust them to your needs. What is powerful with setting up a color system like this is that you can change the color value in one place, and the colors relative to this will automagically follow.

Syntax:

css/* hsl(), rgb() etc. */
color-function(from origin-color h s l / alpha)

/* color function */
color(from origin-color colorspace channel1 channel2 channel3 / alpha)

This is quite useful in different scenarios. Here are some examples.

Hover / active / focus states:

css:root {
  --primary-color: #c30c15;
}

button {
  background-color: var(--primary-color);

  &:hover {
    background-color: hsl(from var(--primary-color) h s 80)
  }
}

We can also calculate the values, like increasing (or reducing) the lightness:

css:root {
  --primary-color: #c30c15;
}

button {
  background-color: var(--primary-color);

  &:hover {
    background-color: hsl(from var(--primary-color) h s calc(l + 10))
  }
}

Transparency:

css:root {
  --primary-color: #c30c15;
}

.container {
  background-color: rgb(from var(--primary-color) r g b / 0.5);
}

Light mode / Dark mode:

css:root {
  --base-color: hsl(205 40% 15%);
  --primary-color-10: hsl(from var(--base-color) h s calc(l + 10));
  --primary-color-20: hsl(from var(--base-color) h s calc(l + 20));
  --primary-color-30: hsl(from var(--base-color) h s calc(l + 30));
  --primary-color-40: hsl(from var(--base-color) h s calc(l + 40));
  --primary-color-50: hsl(from var(--base-color) h s calc(l + 50));
  --primary-color-60: hsl(from var(--base-color) h s calc(l + 60));
  --primary-color-70: hsl(from var(--base-color) h s calc(l + 70));
  --primary-color-80: hsl(from var(--base-color) h s calc(l + 80));
  --primary-color-90: hsl(from var(--base-color) h s calc(l + 83));

  &[data-theme="dark"] {
    --base-color-dark: hsl(from var(--base-color) h s calc(l + 80));
    --primary-color-10: hsl(from var(--base-color-dark) h s calc(l - 10));
    --primary-color-20: hsl(from var(--base-color-dark) h s calc(l - 20));
    --primary-color-30: hsl(from var(--base-color-dark) h s calc(l - 30));
    --primary-color-40: hsl(from var(--base-color-dark) h s calc(l - 40));
    --primary-color-50: hsl(from var(--base-color-dark) h s calc(l - 50));
    --primary-color-60: hsl(from var(--base-color-dark) h s calc(l - 60));
    --primary-color-70: hsl(from var(--base-color-dark) h s calc(l - 70));
    --primary-color-80: hsl(from var(--base-color-dark) h s calc(l - 80));
    --primary-color-90: hsl(from var(--base-color-dark) h s calc(l - 85));
  }
}

Disabled element:

css:root {
  --primary-color: #c30c15;
}

button {
  background-color: var(--primary-color);

  &.disabled {
    background-color: hsl(from var(--primary-color) h 10 l / 0.7)
  }
}