CSS Color Manipulation Functions, Please Save Us From The CSS Custom Property Gotcha

I think it’s so annoying that this doesn’t work:

html {
  --brandColor-h: 27;
  --brandColor-s: 92%;
  --brandColor-l: 42%;
  --brandColor: hsl(
    var(--brandColor-h) var(--brandColor-s) var(--brandColor-l) /
      var(--brandColor-a, 1)
  );
}

a {
  color: var(--brandColor);
}
a:hover,
a:focus {
  --brandColor-l: 60%;
}Code language: CSS (css)

Hopefully, you can see what I’m trying to do there. The links are a special color, and in their hover/focus state, I want to keep that color but change just the lightness. That seems like bread-and-butter CSS custom properties stuff. But it’s a gotcha, and while there are workarounds (referenced in that CSS-Tricks article), none of them feel great to me.

This kind of manipulation only works if the CSS selectors all match the same thing. Manuel Matuzović blogged a recent example:

[role="status"] {
  --h: 206deg;
  --s: 74%;
  
  --background-color: hsl(var(--h) var(--s) 90%);
  --border-color: hsl(var(--h) var(--s) 70%);
}

.warning {
  --h: 40deg;
}
.error {
  --h: 0deg;
}Code language: CSS (css)

That’s fine because all those selectors match the same DOM element. Something like <aside role="status" class="warning"> or the like.

Adam calls them “partial props”.

But all we’re doing really is exploiting the fact that the hsl() value happens to have numeric values that make it easy to do the kind of manipulation we want. I’ll shout out OKLCH again, as it retains that human readability and manipulability.

What we really want to do is manipulate the lightness of a color no matter what format it is originally in. Or any other aspects of that color. Both Dave and Tyler pointed to the Relative Color Syntax on their 2023 CSS Wishlist. So in the future, (it works in Safari Technology Preview as I write), we’ll do this instead:

html {
  --brandColor: hsl(27 92% 42%);
}

a {
  color: var(--brandColor);
}
a:hover,
a:focus {
  color: hsl(from var(--brandColor) h s calc(l + 18%));
}Code language: CSS (css)

That from syntax (where it doesn’t even matter what format the original color was) and the ability to manipulate the individual values in the function is so great.

Thoughts? Email me or comment below. Also CodePen PRO is quite a deal. πŸ™

Leave a Reply

Your email address will not be published. Required fields are marked *