Skip to content

Web Animation Gotchas

This is an excellent overview of using the Web Animation API.

I meant to share this a month ago when I first saw it, but it came up again recently when I was making some animation improvements to a website I've been working on, so there's no time like the present.

I made some minor changes to the animateTo function included in the video for my own purposes, so the snippet I use is along the lines of:

function animateTo(element, keyframes, options) {
  let cleanup = () => {};
  return new Promise((resolve, reject) => {
    try {
      const animation = element.animate(keyframes, {
        ...options,
        fill: "both",
        signal: undefined,
      });

      const finish = () => {
        try {
          animation.commitStyles();
          animation.cancel();
          resolve();
        } catch (e) {
          // handle browsers that don't support `Animation.prototype.commitStyles`
          reject(e);
        }
      };
      animation.addEventListener("finish", finish);

      // While the animation is not exposed through `animateTo`,
      // animations can still be cancelled via the `signal` option,
      // or when accessed from `Element.prototype.getAnimations`
      const cancel = () => reject();
      animation.addEventListener("cancel", cancel);

      // Add support for AbortController
      const signal = options.signal;
      const abort = () => animation.cancel();
      if (signal) {
        signal.addEventListener("abort", abort);
      }

      cleanup = () => {
        animation.removeEventListener("finish", finish);
        animation.removeEventListener("cancel", cancel);
        if (signal) {
          signal.removeEventListener("abort", abort);
        }
      };
    } catch (e) {
      // handle older browsers that don't have `Element.prototype.animate`
      reject(e);
    }
  }).finally(cleanup);
}