Staggering Animations
The following is a guest post by David DeSandro. David wanted to offer a new feature in Isotope: staggered animations. Like so many things web, there are lots of ways he could have approached it. Here he looks at some of the possibilities, the advantages and disadvantages of each, and what he ultimately went with for Isotope.
Consider this cinematic Seinfeld moment:
The image of George running through a group of gulls stirs the emotions. The energy in his conviction is matched by the bursting energy of the birds. So how can we animate with this kind of energy?
Take another look at those gulls. It’s not that there’s a lot of them. The birds take flight individually. As each one flies, their numbers in grow, and the emotion lifts off with them. Go get ’em George!
Instead of animating a group of items all at once, we can recreate this same effect by staggering the animations. When each item’s animation is incrementally delayed, they appear as individuals, but still move collectively as a whole. The result is captivating and feels more true to life.
I recently released Isotope v3 with new staggered item transitions.
See the Pen Isotope – stagger by David DeSandro (@desandro) on CodePen.
While item transitions are easy to set up, they can be difficult to manage. Running multitudes of animations at different intervals gets complex. So let’s explore how to stagger item transitions.
We’ll used a simple animation for our example: moving a group of items horizontally. Items have CSS transition: transform 0.4s;
. They move by toggling .is-moved
class. The first demo moves all the items at once.
See the Pen single transition by David DeSandro (@desandro) on CodePen.
setTimeout
We can use setTimeout
to stagger triggering the transitions. setTimeout
will start the transition later with a delay in JavaScript.
See the Pen setTimeout by David DeSandro (@desandro) on CodePen.
This actually looks pretty good. To fine tune the animation, I want the items to move without overlapping. So items on the right start moving first when moving to the right. Items on the left start moving first when moving to the left. We need to reverse the setTimeout
delay if moving to the right.
See the Pen setTimeout, forward & reversed by David DeSandro (@desandro) on CodePen.
Not bad! But now comes the premier test of any animation system: What happens when a change is triggered while animating? This edge case is too often overlooked. Any novice developer can add an animation. But if you care about your users, your animations should react instantly when acted upon. Animations should not impede on your users actions.
Try clicking the button while transitioning to see what happens.
It works. All the items end up where they are supposed to. But I don’t like how it behaves. It looks like the items get confused. Also try the non-reversed demo.
The forward/reversed transition continues through all the items. This isn’t good. The animation is still happening after the user has already reversed their action.
transition-delay
Let’s try something else. We’re already using CSS transitions, so it makes sense to use transition-delay
. This demo uses JavaScript to set the incremental transition-delay
in JS (but you could also use CSS preprocessor logic if that’s your thing). The transition is triggered at the same time for all items, but their delay differs by their transition-delay
value.
See the Pen transitionDelay by David DeSandro (@desandro) on CodePen.
We can reverse the delay, to have similar behavior moving left and right, just like the setTimeout
demo.
See the Pen transitionDelay, forward & reversed by David DeSandro (@desandro) on CodePen.
As for start-stopping, this transition-delay
demo behaves differently. The forward/reversed demo stops in place for moment.
This could work, but its behavior still isn’t ideal.
Frame-based animation
There’s one more method to try out: frame-based animation. Using requestAnimationFrame
allows us to have control of how each transition is triggered, when it is triggered.
See the Pen frame animation by David DeSandro (@desandro) on CodePen.
It’s got perfect behavior. Start-stopping reverses the animation right where it is, so there is no delay and no excess transitions. But this nice result comes at the cost of complexity. This demo requires double the amount of JavaScript, with an animation loop that has to run every frame.
So if you want to stagger animation, you’ve got options.
setTimeout
will work, but is hard to cancel.transition-delay
will work, but might have delays.requestAnimationFrame
will work, but requires more JavaScript.
And there are lots more solutions out there: CSS animations, jQuery .animate()
, GreenSock, D3, yada, yada, yada. All these solutions can be used for staggering animations. But I encourage you to investigate how well they hold up to edge cases when user actions occur during the animation.
Working on Isotope, I chose to use the transition-delay
technique. It provided the best level of control, without too much complexity. Now Isotope users can add the final level of polish to their UI and take their experiences to new levels. Like a Costanza chasing his dreams.
Staggering Animations is a post from CSS-Tricks