csscss-variablescss-calcoklch

Make a given oklch color 50% lighter via CSS oklch(from ...) and calc() function


We have a design system that comes with a number of CSS custom properties for colors, e.g.:

:root {
  --color--blue-1: oklch(88.6% 0.023 238);
}

We're using the relatively new color format oklch.

Now I need to CSS calc() a color that is 50% lighter, using the oklch(from...) function. I cannot use opacity or alpha for the task because it needs to be a solid color that remains the same regardless of any background.

The desired result would be

:root {
  --color-blue-1-50: oklch(94.2% 0.023 238);
}

The formula is simple: Just pick the l from lch, then the new l_new will be:

l_new = l + ((100% - l) / 2)

So basically, just add half of what's missing to 100% to the l in lch.

How can I put this into a CSS calc function like this:

:root {
  --color-blue-1-50: oklch(from var(--color-blue-1) calc(/* these are the missing bits */) c h);
}

I tried this, but it just shows up as an invalid value:

:root {
  --color-blue-1-50: oklch(from var(--color-blue-1) calc(l + calc(100% - l / 2)) c h);
}

:root {
  --color-blue-1: oklch(94.2% 0.023 238);
  --color-blue-1-50: oklch(from var(--color-blue-1) calc(l + (100% - l) / 2) c h);
}

div {
  display: block;
  height: 100px;
  width: 100px;
}

.original {
  background-color: var(--color-blue-1);
}

.fifty-percent-lighter {
  background-color: var(--color-blue-1-50);
}

.faked {
  opacity: 0.5;
}
<div class="original">original</div>
<div class="fifty-percent-lighter">50% lighter</div>
<div class="original faked">50% lighter using opacity</div>


Solution

  • Your formula can also be seen as (l/2 + 50%) then instead of 50% you have to use .5

    :root {
      --color-blue-1: oklch(80.2% 0.023 238);
      --color-blue-50: oklch(from var(--color-blue-1) calc(l/2 + .5) c h);
    }
    
    div {
      display: block;
      height: 100px;
      width: 100px;
    }
    
    .original {
      background-color: var(--color-blue-1);
    }
    
    .fifty-percent-lighter {
      background-color: var(--color-blue-50);
    }
    
    .faked {
      opacity: 0.5;
    }
    <div class="original">original</div>
    <div class="fifty-percent-lighter">50% lighter</div>
    <div class="original faked">50% lighter using opacity</div>