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.
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.
We can use
setTimeout to stagger triggering the transitions.
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.
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.
Let's try something else. We're already using CSS transitions, so it makes sense to use
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
We can reverse the delay, to have similar behavior moving left and right, just like the
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.
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.
So if you want to stagger animation, you've got options.
setTimeoutwill work, but is hard to cancel.
transition-delaywill work, but might have delays.
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.