While reading the MDN page for @keyframes
, which are used to make CSS animations, I saw the sentence:
Declarations in a keyframe qualified with
!important
are ignored.
This seemed surprising. I generally have the sense that adding !important
to a declaration makes that declaration “win out”, i.e. over ones that came earlier in the stylesheet and ones that lack the !important
annotation.
I dug into why this is the case, and understanding it starts all the way back with what “cascading” in Cascading Style Sheets (CSS) means.
One guiding principle of CSS is that multiple different stylesheets can influence how a document is presented. There are two processes that help make this happen:
In cascading, we have different declarations trying to set values for the same combination of element and property, and the cascade figures out which one to use, based on a particular order of precedence.
Defaulting is the opposite: no declarations attempt to set a value for a given element/property combination, so the value defaults to inheriting from the parent or using a property’s initial value.
We’ll be focusing on the cascade, because the @keyframes
quirk is about the conflict between regular animation declarations and !important
ones.
!important
To determine which value wins, the cascade looks at where the declaration came from. There are three core origins:
There are also two origins that arise from extensions to CSS:
The !important
annotation exists to let authors or users move a declaration from its default spot in the precedence order to a certain higher one. A declaration is called important if it contains the !important
annotation. Otherwise, it is normal.
Putting these categories all together, this is the cascade sorting order:
Notice that the three important origins are in the reverse order of the three normal origins. As alluded to before, this can be helpful for accessibility, letting !important
user origin styles override declarations that a website author deems !important
.
Also, notice that all important origins, specifically the important author origin (#4), have more weight than animation (#5). This is something that the CSS specification on animations points out, and the MDN docs reflect.
Once I learned all this, I thought: well, that’s enlightening, but it doesn’t fully explain… why should and why does !important
not work in @keyframes
? Can’t an important declaration in a keyframe just be ✨ extra-emphasized ✨ but effectively do the same thing as a normal one?
Let’s break this down into the why and the how.
The why: As mentioned above, !important
provides a way to shift the balance of power among different style declaration origins. Animations already override all normal declarations, so it’s useful to have something at one’s disposal to override animations. That “something” is !important
.
As for how, I looked into how animation works. It seems that the animation process as a whole looks at the keyframes and then adds appropriate values into the CSS cascade. But the declarations in the keyframes don’t directly interact with the cascade themselves. !important
makes no sense outside the context of cascading(!), so important declarations are invalid and therefore ignored by the animation process.