Check out a free preview of the full Dynamic CSS with Custom Properties (aka CSS Variables) course

The "Invalid Values & Computed Values" Lesson is part of the full, Dynamic CSS with Custom Properties (aka CSS Variables) course featured in this preview video. Here's what you'd learn in this lesson:

Lea demonstrates what happens when an invalid value is passed into a CSS variable, invalid at computed value time (IACVT), discusses parse time, computed values, and used values. The syntax of registered properties is checked at computed value time, not at parse time.


Transcript from the "Invalid Values & Computed Values" Lesson

>> Sweet, so let's talk a little bit about invalid values, because there's a few gotchas here, so this is the same code we've seen before. We have a declaration that sets the background to red and a button a declaration that sets it to whatever accent color is orange as a fallback.

What happens if accent color is 42 degrees is set to 42 degrees, which is a perfectly valid CSS value for another property. But when it's substituted in background, then it produces an invalid background because background 42 degrees is nonsensical, so what do you think will happen there? What color will we get, will we get red, will we get orange, will we get something else, black, transparent like what's your guess?

>> Red.
>> So it most definitely will not be red because by the time the browser reads the second declaration it has already thrown away the first one.
>> Why?
>> Now, it's, so it's actually gonna be transparent but many people expect that it should be orange, I mean, the fallback is orange so why not?

The thing is the fallback is applied when we don't have a value or when the variable is set to initial which is equivalent to not having a value. When we do have a value, like 42 is a legit value for the variable, at that point, since we have a value, the fallback is not applied, the browser substitutes accent color with the value we have.

Like, we might be having other verticals in the same property as well, the browser won't know if the resulting value is valid, until it's done substituting all of these vital functions. And if the resulting value is not valid at the end of this process, then the browser's like, okay, what do I do now?

And what it ends up doing is basically setting the property to whatever it would have been if you assigned it the unset keyword. And for those of you that haven't seen the unset keyword before, it's basically equivalent to initial for known inherited properties and inherit, for inherited properties.

So it basically resets the property as much as it can without knowing anything specific about the property, so for backgrounds, the initial values having a transparent background which is what we get. This is very different from having invalid values without variables, before variables, before variables if we had background red and then background 42 degrees, we would get red.

That is the reasonable behavior, but for technical reasons, it was not feasible for CSS, the variables are substituted after the CSS code has been parsed. So we don't actually have access to the first declaration, the background read that declaration, so the browser needed to figure out something else something else that it could do.

This concept is called invalid that computed value time we're gonna be seeing it throughout it's a very important concept, it's not, it's often abbreviated in CSS circles as IACVT. I'm just gonna say invalidate computed value time when we say this, cuz this is just a really weird acronym.

So what is a computed value, there are three main stages in resolving a CSS value, they're actually more, but these are the three main ones, first, there is parse time. There is when the browser reads, the specified values as they've been provided, this is when the browser goes through the CSS code.

Reads it, pauses it, creates an abstract syntax tree, creates a tree of objects, the CSS object model, this is basically a one-and-done operation, it's done once. It does not re-done when dimensions change, when the windows or is resized it's just done once when the CSS code changes. CSS code is repurposed only when the actual CSS code changes like when we override the style element for example, and in most cases, it's only done once.

For example, this is when duplicate properties in the same rule are removed and this is when shortcut properties are expanded to their long hands. Then there is computed values which is when most relative values are resolved but not completely. There are certain relative values that are only resolved later because they require expensive operations.

So for example, this is when relative units will be resolved to pixels for example viewport units. But percentage widths will not be resolved at computed value time they will be resolved at what we say used value time. Because that's an expensive operation, the browser leaves it as late as possible and there's certain things that are done as late as used value time.

For example, currentcolor is also resolved then, many people think that currentcolor is resolved at computed value time, the currentcolor keyword. But it's actually only resolved at used value time, the main distinction that we're gonna make in this workshop is parse time versus computed value time. Remember when earlier, we said that the syntax of registered properties is checked at computed value time and not parse value time.

And that is why we cannot test for at properties support via feature queries and it was a bit hand wavy at the time now you know what that means. And another thing to remember is that invalid computed value time is essentially equivalent to the onset keyword that is the end result of this.

Anytime a property becomes invalid computed value time, it's essentially set to unset, let's look at another example. So here, we have a slightly different example but it's still setting the background to red and then setting it to accent-color with a fullback of 42 degrees. So when accent color is not set or when it's set to initial, what do we get?

>> Three people said transparent like right after people said red and white, any guesses, looks like someone's guessing transparent.
>> The people who guessed transparent are correct, the reason we get transparent is let's take it step by step. So obviously, we won't get background red that's thrown away at parts time that's gone we'll never see it again, now, accent color has the value initial so the full back is triggered.

So we get background 42 degrees and since at that point, all we have is a declaration with background 42 degrees which is invalid. It has to become invalid computed value time which gives us the same as unset which for background gives us transparency. So one thing to remember is that fallbacks can also trigger invalid computed value time, basically anytime as a result of variables the browser ends up with a declaration that doesn't make sense.

That triggers invalid computed value time and this concept was actually introduced when we designed CSS variables. But in the future we plan to use it for other things as well like for example, in the future, we want to make it possible to divide values and calc with lengths.

And this might be an avenue to make it happen, in the previously, it wasn't possible because of potential division by zero. So let's look at some more examples, you, I'm not sure if you've heard of LCH colors, so HSL colors have a bunch of drawbacks even though they're more human friendly.

The same difference in HSL coordinates can produce callers with vastly different, actual color differences, whereas LCH is designed to be perceptually uniform. So it doesn't have this problem, and also LCH can access the entire gamut of colors in a modern screen. Whereas HSL colors are restricted to sRGB, which in today's screen is like two thirds of the colors that the screen can produce.

So right now, only Safari supports LCH colors, so what happens if we try to do both, if we try to use LCH colors with some standard CSS color fullback? So as you probably know, all of these code snippets would produce the intended LCH color when LCH is actually supported.

But when LCH is not supported, they can produce different results, so the first bit of code you probably know what that would produce. It would produce gold when LCH is not supported that is what we've been doing for fullbacks for decades of using CSS. So now with custom properties, it's very common to define global colors on custom properties, so what happens if we wanna use LCH colors, what happens in that case?

So you might be able to guess that if a browser doesn't understand LCH, then once it substitutes it into the background declaration. It sees an invalid value and this results in an invalid computed value time declaration which makes it transparent. In the third code example, this actually produces the exact same result, it doesn't help, for that, the cascade happens in the color property.

Because the color property at this point, the browser doesn't know that this can only contain colors, it just sees two declarations for the same custom property. So it throws away the first one, it gets the second one, then tries to substitute it in background and sees that it's not valid.

Here's another example, what do you think this might produce, so we've actually registered our code, our color property here and we've said it has to be, it can only contain colors. We've given it an initial value of sky blue, which is probably not a very good initial value for properties in general, but here let's see what's going on.

And then we've assigned a gold color on it, which every browser understands and the, and in the same rule. We've assigned an LCH color on it, which only safari understands, so that, what will happen in other browsers that are not Safari?
>> Sky blue.
>> That's clever, indeed, it's going to be sky blue but why does this happen?

The reason this happens is that the property that actually goes into invalid computed value time mode is not background now, it's the color property. So, when we try to assign the LCH value on the color property, the browser sees that this is not valid. And it sees this not at parse time because as we've said, the syntax of registered properties is only check that computed value time, at parse time anything goes.

So then this property becomes invalid at computed value time and when a property becomes invalid at computed value time it goes to its initial value, which is, sky blue. So some people might wonder, why did we end up with this behavior, it's a little bit unintuitive, why do custom properties check their syntax at computed value time?

And not at parse time like real CSS properties that the browser supports, so the reason for this is actually with a bit technical. It's that register new properties which could happen at any time would trigger a reparse of the entire stylesheet. Like you could add an add property rule through JavaScript or you could call CSS register property and then you would trigger a reparse of the entire style sheet.

If these would check the parse value time, which is, in parsing an entire style sheet is a very expensive operation. So we did not wanna introduce a to performance foot gun, and this is why their syntax is checked at computed value time, this is definitely something to remember.

It can be quite confusing, what's going on if you don't know that their syntax is checked that computed value time and not parse time. Many people assume that it should be checked at parse time cuz that's what's reasonable.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now