skip to content

In CSS, how do declarations coming from a running transition or a running @keyframes animation rank against ordinary declarations and against !important ones?

level: middleimportance: nice to knowfreq 26%

answer

  1. both get their own cascade slot
  2. animations above normal, below important
  3. transitions sit at the very top
  4. !important pins an animated property
  5. important inside @keyframes is dropped

basics

~20 s

Animation declarations sit above all normal declarations but below every important one, so an !important rule freezes an animated property. Transition declarations sit at the very top of the cascade, above even important declarations, for as long as the transition is running.

solid answer

~40 s

Both get their own slot in the origin-and-importance ordering. Declarations produced by a running `@keyframes` animation rank above all normal declarations from any origin, which is why an animation visibly overrides the element's static styles — but they rank *below* every important declaration, so an author `!important` on an animated property will pin it and the animation appears to have no effect on it. Declarations produced by a running transition rank at the very top, above important declarations, for the duration of the transition; that is deliberate, because a transition is interpolating toward a value the cascade already chose and must not be interrupted mid-flight. One related gotcha: `!important` written inside a `@keyframes` block is ignored outright — the specification does not allow it there.

code

css · 9 lines
css
.box {
  background-color: blue !important;
  animation: pulse 1s infinite;
}

@keyframes pulse {
  from { background-color: red; }
  to   { background-color: yellow; }
}

go deeper

for a junior

Know that a running animation overrides the element's ordinary styles for the properties it touches, and that an !important declaration on such a property can stop it from changing.

for a middle

Place both slots in the origin-and-importance ordering: animations above all normal declarations but below every important one, transitions above everything. Explain why importance inside @keyframes is discarded.

for a senior

Diagnose with it — reach for the cascade when one animated property is frozen while the animation clearly still runs, and explain why a value can look correct mid-transition and wrong the instant it ends.

for a principal

Frame the tradeoff for a team: !important in shared component CSS silently disables motion and theming downstream, so decide where the flag is permitted before an animation bug forces the conversation.

## Where animations and transitions live in the cascade The cascade's first sort step is usually described as three origins times two importance levels, but the full ordering has two extra slots for declarations the browser generates itself. Weakest to strongest: ``` user-agent normal user normal author normal --> CSS animations (declarations from a running @keyframes) author !important user !important user-agent !important --> CSS transitions (declarations from a running transition) ``` These are not stylesheets you wrote; they are values the animation and transition engines contribute for as long as they are active. When the animation or transition is not running, nothing is contributed and the ordinary declarations resolve normally. ## Animations: above normal, below important A running animation must be able to override the element's ordinary styles — otherwise `@keyframes` would be useless — so animation declarations outrank every normal declaration from every origin. ```css .box { background-color: blue; } .box { animation: pulse 1s infinite; } @keyframes pulse { from { background-color: red; } to { background-color: yellow; } } ``` While `pulse` runs, the interpolated `background-color` wins over the static `blue`. But animation declarations sit *below* the important buckets. Add one line and the animation stops affecting that property: ```css .box { background-color: blue !important; } ``` The element keeps animating — the animation is still running, `animationstart` still fires — but `background-color` is pinned to blue, because the important author declaration outranks the animation slot. This is a classic "my animation doesn't work" bug, and the fix is to remove the `!important`, not to add one somewhere else. Which property values an animation contributes at all depends on the keyframes and on `animation-fill-mode`; outside the active window, with the default fill mode of `none`, the animation contributes nothing and the underlying declarations show through unchanged. ## `!important` inside `@keyframes` is ignored Because the position of animation declarations in the cascade is fixed by the animation slot, importance inside a keyframe would be meaningless — so the specification says declarations in a keyframe qualified with `!important` are ignored: ```css @keyframes bad { to { opacity: 0 !important; } /* the whole declaration is dropped */ } ``` Note the consequence: it is not that the `!important` is stripped and `opacity: 0` still applies — the declaration itself is thrown away, so that keyframe simply has no `opacity` in it. ## Transitions: above everything Transition declarations sit at the very top, above important declarations of any origin. The reasoning is different from animations. A transition is not an independent source of styling: it fires *because* the cascade produced a new value for a property, and it interpolates from the old value to that new one over a set duration. If an `!important` declaration could outrank the in-flight value, the property would snap between states while the transition ran, which is exactly the artefact the transition exists to remove. So for the duration of the transition, the interpolated value wins; when the transition ends, nothing is contributed any more and the cascaded value — the target the transition was heading to — is what remains. This is easy to misread as "transitions beat `!important`", which is true but incomplete. The important declaration is still the winner of the ordinary cascade; the transition is merely interpolating *toward* whatever the cascade chose and holding the intermediate values while it does. ## Practical takeaways When an animated property refuses to animate, grep for `!important` on that property before suspecting the keyframes. When a keyframe seems to have no effect on one property, check whether you wrote `!important` inside it and it was discarded. And when you see a value flicker into place at the end of an interaction, remember that the transition slot releases the moment the transition finishes — after that, the ordinary cascade result is all that is left, so any mismatch you see afterwards is a cascade problem, not an animation one. In interviews this is usually a probe rather than a screener: it checks whether "`!important` beats everything" is a slogan or a model. The clean answer is that both animations and transitions occupy fixed slots in the same origin-and-importance ordering — one below the important band, one above it.

  • Why do transitions rank above important declarations while animations rank below them?
    Because they play different roles. An animation is an independent source of values that competes with your styles, so the cascade puts it below the escape hatch you control. A transition is not competing at all — it interpolates toward the value the cascade already chose, so letting anything outrank it mid-flight would defeat its only purpose and produce the snap it exists to smooth.
  • An element is animating but one property never changes. What do you check first?
    Whether that property carries `!important` anywhere in the author styles. Important author declarations outrank the animation slot, so the animation keeps running and firing its events while that one property stays pinned. The second check is whether the `!important` is inside the `@keyframes` block itself, where the declaration is discarded entirely.

saying these in an interview costs you the question

  • Says !important beats absolutely everything including transitions
  • Thinks animations outrank important declarations
  • Believes !important inside @keyframes strengthens that keyframe
  • Assumes a pinned property means the animation is not running
  • Treats animation and transition as occupying the same cascade slot

context