container chevron {transform: rotate(0);transition: transform 5s;}container:active chevron {transform: rotate(180deg);}
Maybe we can get part or most of the way to this goal with incremental changes, like:* When an input event happens that will cause a state change, do the rendering update + early commit to start an animation when possible before running other tasks (we recently shipped a change to prioritize rendering in this situation)
* will-change already exists to reduce computation delay for starting the animation; consider adding more values if something is missing
* Add more pseudo classes and async events (similar to the `toggle` event for popover) that cannot be preventDefaulted / have async event handlers, to make it more foolproof for developers to start animations without initial jank
* Add passive event listeners (Scott is planning that for later this year)
The nice thing about these is they won't require interpreting gestures on the compositor, detecting whether potential state changes would cause animations that are compostable, or representing a paused animation on the compositor thread.
A few observations...On Thu, Apr 17, 2025 at 11:03 AM Chris Harrelson <chri...@google.com> wrote:Maybe we can get part or most of the way to this goal with incremental changes, like:* When an input event happens that will cause a state change, do the rendering update + early commit to start an animation when possible before running other tasks (we recently shipped a change to prioritize rendering in this situation)We are already getting pretty much all the benefit possible along these lines: after Scott's recent work, we pause non-rendering tasks on the main thread after an input event is processed, until the rendering update is done. We can't initiate a main thread rendering update before the compositor thread asks for it, because the compositor thread bundles essential information with the BeginMainFrame task.
* will-change already exists to reduce computation delay for starting the animation; consider adding more values if something is missingwill-change reduces the composited layer allocation work, but that work is unlikely to be a significant contributing factor to slow input response at the high percentiles. It is almost certainly dwarfed by the time spent running user script.
* Add more pseudo classes and async events (similar to the `toggle` event for popover) that cannot be preventDefaulted / have async event handlers, to make it more foolproof for developers to start animations without initial jankThis is definitely something we should investigate, but I'm not strongly confident that it will be feasible because I think it will be very difficult to accurately detect state changes in pseudo-states on the compositor thread. By way of contrast, I think detecting/interpreting input events would be much easier.
* Add passive event listeners (Scott is planning that for later this year)100%, but I think this is orthogonal.
Also, I didn't know that we already have a way to model a paused animation in cc. Was that introduced because of scroll-driven animations?
Style-dev,We have a potential secondary launch approach for declarative interactions (details here), and it depends on being able to efficiently pre-compute the effect of a hypothetical css pseudo class change ahead of time. For example:container chevron {transform: rotate(0);transition: transform 5s;}container:active chevron {transform: rotate(180deg);}I would like to set up a paused compositor transition for chevron from rotate(0) to rotate(180deg) in preparation for starting this transition on the compositor thread in response to a user interaction that would activate :active on container. There are many cases where this can get hard, such non-composited property changes (e.g., layout), precedence issues, and non-local effects (e.g., changes to styles on other elements), and I am okay with only creating my compositor transition for the easiest cases.
Doing a forced :active style update during the paint lifecycle phase would be problematic because this could dirty style/layout and cause additional frames, so I think this needs to either occur during style recalc, or in a way that doesn't dirty the real style/layout. Is there a way?
On Thu, Apr 17, 2025 at 1:40 AM Philip Rogers <p...@google.com> wrote:Style-dev,We have a potential secondary launch approach for declarative interactions (details here), and it depends on being able to efficiently pre-compute the effect of a hypothetical css pseudo class change ahead of time. For example:container chevron {transform: rotate(0);transition: transform 5s;}container:active chevron {transform: rotate(180deg);}I would like to set up a paused compositor transition for chevron from rotate(0) to rotate(180deg) in preparation for starting this transition on the compositor thread in response to a user interaction that would activate :active on container. There are many cases where this can get hard, such non-composited property changes (e.g., layout), precedence issues, and non-local effects (e.g., changes to styles on other elements), and I am okay with only creating my compositor transition for the easiest cases.Maybe, if you can ignore cascading and effects on other elements. As long as you resolve style for a single element without setting the resulting style on the Element/LayoutObject and make sure any created animation effects are isolated from the "normal" ElementAnimations.
<!doctype html><style>@keyframes spin {from { rotate: 0deg; }to { rotate: 180deg; }}.title {animation-trigger-name: spin-trigger;}.chevron {animation: spin 0.25s forwards paused;animation-trigger: pointerdown(spin-trigger) once;}</style><div class="title">title</div><svg class="chevron" style="width: 24px; height: 24px;"><path d="M16.59 8.59 12 13.17 7.41 8.59 6 10 12 16 18 10Z"></path></svg>
<!doctype html><style>.title:active ~ .chevron {transform: rotate(0deg);}.chevron {transform: rotate(180deg);transition: transform 0.25s;}</style><div class="title">title</div><svg class="chevron" style="width: 24px; height: 24px;"><path d="M16.59 8.59 12 13.17 7.41 8.59 6 10 12 16 18 10Z"></path></svg>
I'm not saying it's not quite a bit of work.Have you considered a separate CSS syntax for such animation effects to make it clear to the author that there is a limited and well-defined set of what you can do?Doing a forced :active style update during the paint lifecycle phase would be problematic because this could dirty style/layout and cause additional frames, so I think this needs to either occur during style recalc, or in a way that doesn't dirty the real style/layout. Is there a way?Not out-of-the-box readily available API, but I think the way I imagine it could be done it wouldn't need to happen during the style recalc traversal. E.g. a StyleResolver API that is called for a single element, that temporarily forces the active-state to true (like devtools can), does the cascading and computes the ComputedStyle, and stores the new animation effects isolated from the "normal" effects that I mentioned earlier, so that you can pass those separate effects to the compositor somehow.--Rune Lillesveen