javascriptcssanimationweb-animations

Animation commitStyles does not actually set styles


I'm trying to call commitStyles() after an animation is complete so that the styles are retained at the end (by adding to the inline styles) in a way that is performant. However, nothing seems to happen from calling commitStyles, the element just returns to its initial styles after the animation.

Why does calling Animation.commitStyles not work at the end of an animation?

document.querySelector("button").addEventListener("click", function(evt) {
  var a = document.getElementById("target").animate([{
    transform: 'translateX(400px)'
  }], 1000);
  a.finished.then(() => a.commitStyles());
});
<div id="target">I can move</div>
<button>Move it</button>


Solution

  • The default fill for an animation is "none", which makes an element revert back to its original styles after the animation completes. Calling commitStyles at this point has essentially no effect.

    Instead, you can use the "forwards" fill to keep the styles after the animation. Then, call commitStyles() after the animation finishes and immediately cancel the animation to ensure that no more resources are consumed by it. Note that setting the fill can achieve the effect of persisting styles by itself, but there are several drawbacks; for instance, it is difficult to change any styles on an element set by an animation (not using commitStyles) and the browser has to maintain the animation indefinitely.

    document.querySelector("button").addEventListener("click", evt => {
      document.getElementById("target").animate([{
        transform: 'translateX(400px)'
      }], {
        duration: 1000,
        fill: "forwards"
      }).finished.then(a => {
        a.commitStyles();
        a.cancel();
      });
    });
    <div id="target">I can move</div>
    <button>Move it</button>

    As an aside, you can see that calling commitStyles does work before the animation finishes (without setting fill) since the animation styles are still active at that time.

    document.querySelector("button").addEventListener("click", evt => {
      const anim = document.getElementById("target").animate([{
        transform: 'translateX(400px)'
      }], 1000);
      // Do NOT use this approach
      setTimeout(() => anim.commitStyles(), 950);
    });
    <div id="target">I can move</div>
    <button>Move it</button>