[csswg-drafts] [css-animations-2][web-animations-2] Allow preserving animation state after regaining box (#13090)

ydaniv has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-animations-2][web-animations-2] Allow preserving animation state after regaining box ==
According to web-animations-2 the state of an animation is reset if the element owning the animation loses its box and then gets it recreated, i.e. get a computed `display: none` and then back to anything other than `none`. From the spec:

> If an element has a display of none and its display value had computed to none when ignoring the Transitions and Animations cascade origins, updating display to a value other than none will start all animations applied to the element by the [animation-name](https://drafts.csswg.org/css-animations-1/#propdef-animation-name) property.

There are cases, though, where you would not want this to happen, and after getting the animation played once, you'd want it to stay in its finished or removed state. Especially when considering animations that use an Animation Trigger, e.g. with a type of `once`. So, for example, you'd want the element to not get the animation replay if the element got hidden and shown again.

Here is a simple demo: https://jsbin.com/pixixolife/edit?html,css,js,output

In the above demo `animation-trigger` is polyfilled using an animation that starts `paused` with a `delay: 1ms` and `fill: backwards`.
I'm getting the animations and playing them via JS.
Then when clicking the `Toggle display` button the divs get `display: none` and then back to `block`.
Since one of them gets a `data-done="done"` attribute it gets `animation: none`, while the other gets its animation reset, and hence remains invisible.

To give a simple real-life use-case, imagine these divs live inside panes of a Tabs component that get toggled display on and off.

### Solution

Probably the only way to get around backwards compatibility here is to have a new opt-in property for preserving state.

### Questions

1. Do we want/have to set it per animation? Or could we have an inhertited-by-default property, like `interpolate-size`, that can be set once? e.g. on `:root`.
2. Should this be a sub-property of `animation`? Or should it be just named `animation-*` so that it can live on the `:root` and not be reset by `animation`?

### Proposal

My preference is adding a new property like `animation-state`, which is _NOT_ a sub-property of `animation`, and is inherited by default.
Possible values can be `normal` and `keep`, and of course `normal` as initial value.
All is bikeshedable.
This property should probably be a coordinated-list property that corresponds to `animation-name`.
In case of `animation-state: keep` the state of the animation is kept on the element for its entire lifespan, even if it loses its box, or is removed from the DOM. So that if it gets its box recreated, or is re-inserted into the DOM, the state of that animation is maintained.

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/13090 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Tuesday, 11 November 2025 09:03:39 UTC