Repository navigation
Canceling a @keyframes animation freezes the computed style for a later transition on the same element #48225
Description
Activity
- addedC-untriagedNew issues that haven't been triaged yetNew issues that haven't been triaged yet
on Sep 20, 2026 This is the same bug as #48210, right?
This is the same bug as #48210, right?
I can't confirm this without testing, but they look like different bugs. #48210 is about new keyframes not replacing old ones. This issue is about the style freezing after an animation is canceled, because the set isn't marked dirty. So, different repro, different cause.
OK. I was thinking, like, maybe the replacement keyframes cancel the old animation and start a new one (which is what looks like happens in Firefox).
@neeopy thanks for the investigation and potential fix. Can you open a PR for Stylo to fix the bug and a corresponding PR for Servo which updates Stylo and adds the reproduction case as WPT test?
@neeopy thanks for the investigation and potential fix. Can you open a PR for Stylo to fix the bug and a corresponding PR for Servo which updates Stylo and adds the reproduction case as WPT test?
Sure
@TimvdLippe prior to submitting the PR, I reviewed this section again and identified two additional bugs within the same function (
ElementAnimationSet::update_animations_for_new_style,style/servo/animation.rs:1288-1304) that result in the same symptom (frozen computed style) triggered by different factors. I'm documenting them here instead of creating new issues, as they belong to the same root cause category and have the identical fix location as the previous one.If the stylesheet removes the only
@keyframesrule that corresponds to an element's animation-name, and that animation-name is still declared, the animated value will freeze at the last computed state at the moment the rule was removed, rather than reverting to the element's default non-animated style. Reproduces on: repro-keyframes-removed.htmlThe second case follows the same pattern: a missing cascade invalidation, just triggered differently. When the new style applies display: none, cancellation happens after the rule substitution and recascade instead of before it, so the old animation rule gets evaluated one more time before being removed. This lets a stale animated value reappear once the element becomes visible again. Reproduces on: repro-display-none-ordering.html
- added a commit that references this issue
on Sep 21, 2026 - added and removedC-untriagedNew issues that haven't been triaged yetNew issues that haven't been triaged yet
on Sep 23, 2026
Describe the bug:
When canceling a
@keyframesanimation and subsequently initiating a CSS transition on the same element, the computedtransformmay remain static and fail to update. This occurs despite the transition being correctly declared and theanimation-nameset tonone. However, applying the same transition to a new element functions as expected.To Reproduce:
After cancellation,
#boxremains frozen at its last animatedtransformvalue instead of transitioning between 0 and 400 px, even thoughanimation-nameisnone.The cause is a missing dirty flag update in Stylo’s
ElementAnimationSet::update_animations_for_new_style(style/servo/animation.rs:1288-1304).. This path sets the animation state toCanceledwithout marking the set dirty, unlike the other cancellation paths:for animation in self.animations.iter_mut() { if animation.is_cancelled_in_new_style(new_style) { animation.state = AnimationState::Canceled; + self.dirty = true; } }I confirmed this with manual tests: the original build freezes, adding this line restores all four transitions with correct intermediate and final values, and reverting it brings the freeze back.
Platform:
Arch-based Linux (CachyOS), KDE/Wayland, NVIDIA RTX 2060 SUPER.