I'm experimenting with the web animations API for the first time, and trying to chain some values together. I'm a little confused as for this simple animation, where it will translate 200px along the X axis, then 200px down along the Y axis once the first animation is complete.
However, at the end of the animation, it resets the X value of the initial animation. I've tried playing around with 'both' | 'forwards' for the fill mode property, as well as setting translateX to 0/200 in the second transform declaration. Feel like I'm missing something quite simple here.
const box = document.getElementById('box');
const animateRight = box.animate(
[{ transform: 'translateX(0)' }, { transform: 'translateX(200px)' }],
{
fill: 'forwards',
easing: 'ease-in-out',
duration: 2000,
}
);
animateRight.finished.then(() => {
box.animate([{ transform: 'translateY(0)' }, { transform: 'translateY(100px)' }], {
composite: 'add',
fill: 'both',
duration: 1500,
});
});
#box {
width: 100px;
height: 100px;
border: 1px solid black;
}
<div id="box"></div>
Once the first animation finishes, it remains active because of
fill: 'forwards'. Then you performed your second animation where you moved the box downwards. Here's where the problem starts: Naturally, you can't actually have 2 separatetransforms on the same element's style since it's just a single property, so what's really happening is that once the second animation starts, the firsttransformis overwritten. The only reason the box is still to the right during the second animation is because ofcomposite: add—it sort of kept that X displacement, if that makes sense.But then as soon as the second animation actually completes, the animation of course ceases, but because of the
fill: 'both'(which could have also beenfill: 'forwards'—that makes no difference here), you keep the result of the keyframes you specified for the second animation, which is simply translating Y from 0 to 100 and nothing about X.There are 2 ways you can fix the example in this specific question. The first involves using
commitStyles(), and the second involves using the new individual transform properties available in CSS (and consequently WAAPI).Solution 1: Use commitStyles()
The simplest solution would be to call
commitStyles()on the first animation right after it finishes. This will apply the effects of the X translation to the element's actual inline style, so when the first animation finishes, it essentially "saves" that transform style.This approach could be a little janky because of the current issues surrounding
filland the potential of doubling the effect of an animation oncecommitStyles()is called, but that's beyond the scope of this discussion. If you run into issues like that, you can solve them by settingfilltononeimmediately after callingcommitStyles(). Example:Solution 2: Use
translateinstead oftransformIn CSS, you can now actually individually set
translate,rotate, andscaleseparately. For example, the following are equivalent:Naturally, this means you can set those properties using WAAPI as well. Since they are obviously different properties from
transform, you can even use them at the same time. You could havetranslate,scale,rotate, andtransformall acting on the same element at the same time. I removed thecompositeproperty in this example to prove this.Combined with
commitStyles()andcomposite: add(orcomposite: accumulate), the individual transform properties can be extremely powerful in general.