Why is my pulsing jelly blob pausing after one bounce?
const blob = document.querySelector('#jelly-blob');
const pulse = blob.animate(
[{ transform: 'scale(1)' }, { transform: 'scale(1.4)' }],
{ duration: 400, direction: 'alternate', iterations: Infinity }
);
// Reversing direction mid-cycle on hover
blob.addEventListener('pointerenter', () => pulse.reverse());
Reply with what is broken and how you would fix it.
1 Like
The pointerenter event triggers on hover, but there’s no corresponding pointerleave to resume the normal animation direction.
It just reverses and stays reversed. You’d need to add another event listener for pointerleave to call pulse.reverse() again, or pulse.play() if you want it to always go forward after leaving. The current setup means it will only ever reverse once.
1 Like
Spot the Bug answer: The animation reverses direction on pointerenter, but it does not resume its normal alternating behavior after the pointer leaves.
The fix:
Add a 'pointerleave' event listener to call pulse.reverse() again.
Why:
The ‘direction: alternate’ property makes the animation automatically reverse at the end of each iteration. When pulse.reverse() is called, it changes the current playback direction. To restore the alternating behavior, the direction needs to be reversed again when the pointer leaves, effectively setting it back to its original alternating state.
First-answer leaderboard
- @kirupa - 5 (firsts)

- @adnanahmed - 2 (firsts)
- @Apexcodes - 2 (firsts)
- @emmawalter5 - 1 (first)
@Ellen1979
Why is my pulsing jelly blob pausing after one bounce?
const blob = document.querySelector('#jelly-blob');
const pulse = blob.animate(
[{ transform: 'scale(1)' }, { transform: 'scale(1.4)' }],
{ duration: 400, direction: 'alternate', iterations: Infinity }
);
// Reversing direction mid-cycle on hover
blob.addEventListener('pointerenter', () => pulse.reverse());
Reply with what is broken and how you would fix it.
The problem is pulse.reverse().
It reverses the animation’s current direction, but when you hover again, it keeps reversing from wherever it currently is. This can make the animation look like it pauses or behaves strangely.
If the goal is simply to keep the blob pulsing while changing its speed or direction on hover, it would be better to control the animation state rather than repeatedly calling reverse().
For example, if you only want to reverse it once:
blob.addEventListener('pointerenter', () => {
if (pulse.playbackRate > 0) {
pulse.reverse();
}
});
Or, if the normal goal is just a continuous pulse, I’d leave the animation running and change the scale or playback rate on hover instead of reversing it.
You’re right about pulse.reverse() on repeated hovers. It just flips the current playback direction. The issue is that reverse() keeps flipping it from wherever it is. If you want it to always go back to the start of the reverse, you need to reset the animation. You can set pulse.currentTime = pulse.effect.getComputedTiming().duration before reversing. That puts it at the end of the forward cycle, ready to reverse from there.
blob.addEventListener('pointerenter', () => {
pulse.currentTime = pulse.effect.getComputedTiming().duration;
pulse.reverse();
});
Honestly, for a pulsing blob, I’d probably just change the playbackRate on hover instead of reversing. Make it speed up.
blob.addEventListener('pointerenter', () => {
pulse.playbackRate = 2; // Speeds it up
});
blob.addEventListener('pointerleave', () => {
pulse.playbackRate = 1; // Back to normal
});
It’s a smoother effect and less prone to weird states if someone wiggles the mouse.
I like the playbackRate idea a lot for this. it feels more organic for a pulse effect than a hard reverse.
The playbackRate approach is definitely more subtle. I used something similar for a little animation on a client site last year and it just felt right.