CSS Custom Properties Fail Without Fallback

Today I learned! Jeremy Keith wrote about an interesting detail about CSS custom properties, also known as CSS variables, that he learned from Lea Verou: They don’t support the Cascade when a value is invalid. Or, as Lea writes in her article Hybrid positioning with CSS variables and max():

The browser doesn’t know if your property value is valid until the variable is resolved, and by then it has already processed the cascade and has thrown away any potential fallbacks.

Jeremy goes on to explain that this is the reason why using the color() function will fall back successfully if you use it like this:

/* CSS */
p {
  background-color: red;
  background-color: color(display-p3 1 0 0);
}

But it will fail if you use a custom property like so:

/* CSS */
:root {
  --myvariable: color(display-p3 1 0 0);
}
p {
  background-color: red;
  background-color: var(--myvariable);
}

What happens is that the browser first figures out the cascade and then looks at the custom properties. If a property is invalid “at computed-value time”, there is no fallback value because the browser has already thrown away the other values. So in the example above, the browser will not display the red background-color, but instead unset it.

A lot of people are switching from Sass to using CSS custom properties these days. And unless you still have to support IE11, you can totally do that because browser support is solid. So it will only be a matter of time until using CSS variables will have be the new normal. Knowing that they fail all that gracefully is an important thing to know, though. Especially if you are using them to use features that are only supported by a few browsers, like the new color functions color(), lab(), or lch().

But what can you do? Do we have to wait and skip using custom properties for values that might fail? Not really. As I wrote in my recent post about the new color functions coming to CSS, you could use supports() to check for support before setting the properties:

/* CSS */
:root {
  --myvariable: red;
}

@supports (color: color(display-p3 1 0 0)) {
  :root {
    --myvariable: color(display-p3 1 0 0);
  }
}

p {
  background-color: var(--myvariable);
}

Another option would be to use a media-query like color-gamut. But if you want to set many values at once in one ruleset, supports() might be the better solution. Sara Soueidan recently wrote about how she defines Global and Component Style Settings with CSS Variables . In such a case, you could rely on a feature query using supports() to set all the custom properties for supporting browsers.

/* CSS */
:root {
  /* UI Colors */
  --color--primary: rgb(217,0,189);
  --color--secondary: rgb(242,199,0);
}
    
@supports (color: lch(50% 132 334)) {
  :root {
     /* UI Colors for browsers that support LCH colors */
     --color--primary: lch(50% 132 334);
     --color--secondary: lch(82% 132 86);
  }
}

-

This is the 16th post of my 100 days of writing series. You can find a list of all posts here.

~

16 Webmentions

Photo of Adactio Links
Adactio Links
CSS Custom Properties Fail Without Fallback · Matthias Ott – User Experience Designer matthiasott.com/notes/css-cust…
Photo of Matthias Ott
Matthias Ott
Oh… ? Thank you for reporting, Jeremy. I’ll look into it this evening! Have a nice weekend!
Photo of Jeremy Keith
Jeremy Keith
I’m getting an error when I try to send a webmention to that URL from adactio.com/links/17004 > Internal Server Error > Undefined index: photo adactio.com/notes/17007
Photo of Jeremy Keith
Jeremy Keith
CSS Custom Properties Fail Without Fallback · Matthias Ott – User Experience Designer June 13th, 2020 Matthias has a good solution for dealing with the behaviour of CSS custom properties I wrote about: first set your custom properties with the fallback and then use feature queries (@supports) to override those values.
Photo of Kilian Valkhof
Kilian Valkhof
@m_ott should your @supports example here have "--myvariarable: red" in non-supports part? matthiasott.com/notes/css-cust…
Photo of Jens Grochtdreis
Jens Grochtdreis
CSS Custom Properties Fail Without Fallback · Matthias Ott matthiasott.com/notes/css-cust…
Photo of Jacky
Jacky
CSS Custom Properties Fail Without Fallback · Matthias Ott – User Experience Designer matthiasott.com/notes/css-cust…
Photo of Chris Heilmann
Chris Heilmann
👉;🏻; “CSS Custom Properties Fail Without Fallback” 🔗; matthiasott.com/notes/css-cust… Cascade first, custom properties second...
Photo of Front-End Front
Front-End Front
CSS Custom Properties Fail Without Fallback matthiasott.com/notes/css-cust…
Photo of Gary Stevens
Gary Stevens
frontendfront: CSS Custom Properties Fail Without Fallback matthiasott.com/notes/css-cust…
Photo of Refresh Detroit
Refresh Detroit
CSS Custom Properties Fail Without Fallback matthiasott.com/notes/css-cust… #CSS

Likes

Reposts