82% of developers get this 3 line CSS quiz wrong

(I always wanted to do a clickbait title like this and when this chance came along I could not pass it up. 😅 Sorry!)

While putting my ideas into slides for my Dynamic CSS workshop for next week, I was working on a slide explaining how the CSS wide keywords work with custom properties. inherit, initial, unset I had used numerous times and knew well. But what about revert? How did that work? I had an idea, but quickly coded up a demo to try it out.

The code was:

:root {
    --accent-color: skyblue;

div {
    --accent-color: revert; 
    background: var(--accent-color, orange);

Phew, I was correct, but the amount of uncertainty I had before seeing the result tipped me that I might be on to something.

Before you read on, take a moment to think about what you would vote. Warning: Spoilers ahead!





So I posted a quiz on Twitter:

These were the results after the 24 hours it ran for:

orange was the clear winner, and the actual correct answer, skyblue only got 18.1%, nearly the same as transparent!

If you got it wrong, you’re in very good company: not only did 82% of poll respondents get it wrong as well, but even the editor of the CSS Variables spec and co-editor of CSS Cascading and Inheritance (which defines revert), Tab Atkins, told me privately that he got it wrong too: he voted for orange! (Yes, I did get his permission to mention this)

So what actually happens? Why do we get skyblue? I will try to explain as best as I can.

Let’s start by what revert does: It reverts the cascaded value of the property from its current value to the value the property would have had if no changes had been made by the current style origin to the current element.

This means it cancels out any author styles, and resets back to whatever value the property would have from the user stylesheet and UA stylesheet. Assuming there is no --accent-color declaration in the user stylesheet, and of course UA stylesheets don’t set custom properties, then that means the property doesn’t have a value.

Since custom properties are inherited properties (unless they are registered with inherits: false, but this one is not), this means the inherited value trickles in, which is — you guessed it — skyblue. You can see for yourself in this codepen.

What if our property were registered as non-inheriting? Would it then be orange? Nice try, but no. When we register a custom property, it is mandatory to provide an initial value. This means that the property always resolves to a value, even --accent-color: initial does not trigger the fallback anymore. You can see this for yourself in this codepen (Chrome only as of May 2021).

Liked this? Then you will love the workshop! There are still a few tickets left!