Teams‎ > ‎Animations Team‎ > ‎Highlights Archive‎ > ‎

March 2020 - Web Animations, Scroll-linked Animations, Throughput Metrics and more!

March 2020

Chrome Animations Highlights

Archives: go/animations-team-highlights

The Animation Festival

The team made solid progress towards moving Web-Animations forward, as you can see in these demos from Kevin (kevers@) and Hao (haozhes@)!

A kinder gentler cancel - add support for animationcancel

This example illustrates using a combination of CSS animations and CSS transitions, getAnimations, commitStyles and animationcancel to smoothly reset the state of a cancelled CSS animation.

Performing a commit style prior to cancelling the animation prevents the animation from snapping back to the start position.

Within the animationcancel listener we can smoothly transition back to the starting point by triggering a CSS transition.

#box {

  transition: transform 0.5s ease-in-out;


.slide {

  animation: ...



   'animationcancel', (evt) => {

  if( != box) return;

  // Smoothly transition back to

  // starting point. = 'none';


function slide() {



function reset() {


      forEach(animation => {





Taking the scenic route - fix CSS transition events after updating the effect

This example demonstrates a means of customizing the path of a transition by replacing the keyframe effect.

After changing the effect, events still need to be directed to the original target. Previously, changing the effect resulted in dropping the transitionend or tansitioncancel event, which in turn broke the chain of transitions.


    'transitionrun', (evt) => {

  if (evt.propertyName !=='transform')


  const animation = circle.getAniamtions()

      .find(anim =>

            anim.transitionProperty ===


  animation.effect =

    new KeyframeEffect(circle,





    'transitionend', (evt) => { = 0;


// … wait until rendered … =


Playing nicely together - CSS Animation / Web Animation API interactions

This demo illustrates how AnimationEvent.updateTiming overrides properties set via CSS properties.  The updateTiming API may be used to set/override one or more animation properties.  A subsequent change via CSS animation properties must not replace values set via the API call.  The override behavior is on a per-property basis.

Resolve animation ordering issues with free vs markup bound animations

This example illustrates effect ordering and composite: add. Each rectangle starts with a pair of animations: a web animation (scale), and a CSS animation (rotation).  As the CSS Animation has lower composite ordering, the resultant animation is “rotate then scale” which indicates the expected result from before.  In the left rectangle, we grab a reference to the CSS Animation before cancelling (clearing the animation property). When the rotate animation is replayed, it is now a “free” animation and the ordering flips to be creation order: i.e. “scale then rotate”. Since scale and rotate operations are not commutative, we can find the end results are different from the left to right.

--- To be continued ---

Special thanks to Rob (flackr@) and Majid (majidvp@) who reviewed 40+ non-trivial patches for the excellent work.

Scroll-linked Animations

On the standardization front, Majid triaged all outstanding specification issues and identified 12 of them as P1 for the First Public Working Draft (FPWD). Rob proposed progress-based animations for cleaner developer ergonomic (pull request) getting rid of the arbitrary duration that is currently needed. And Olga ( drove the discussion on the inactive timeline spec issue and proposed the timeline state chart.

On the implementation side, this sprint Yi (yigu@) added support for running scroll-linked animations on the compositor to free them from the busy main thread, Majid landed the initial patch IDL changes to support element-based scroll offset, and Jordan ( added ScrollTimeline.phase which will be used specially to replace the fill mode.

Left: the animation becomes janky after adding artificial jank on the main thread.

Right: the animation is composited therefore it’s still smooth with artificial jank.

Finally after sprints of hard work on the rather complex problem, Olga landed the scroll snapshotting work to make the timeline invalidation correct and avoid potential layout cycles. This was a ship-blocker!  \ o /

Frame Throughput Metrics

Xida (xidachen@) made solid progress on refining high-level metrics to measure renderer performance this sprint.

Thread throughput unification

Top: width animation runs on the main thread

Bottom: transform animation runs on compositor

When we have animations running on both main thread and compositor we used to report the one with worse throughput regardless. e.g. the transform animation’s throughput is ~98%; the width animation starts 3 seconds after and its throughput is ~10%. In the past we reported 10%. Now when we are not expecting to produce a main frame such as the first 3 seconds, we take the compositor throughput therefore the reported throughput is ~65%.

Tracking the last frame

It’s possible that after a BeginImpl[Main]Frame is reported, the tracker is scheduled to terminate. e.g. an impl-frame could have started right before a sequence stops such as the end of a touch scroll. We will completely lose track of it under such circumstances. With Xida’s work, we can now track the last BeginImplFrame and soon the last BeginMainFrame

Chrome Animations Highlights | March 2020