Fun with Staggered Transitions
At 4/19/2024
Here’s a neat little solution to a problem I encountered in my quest to use more animation in my interface design work.
I was prototyping a sliding view transition between nested levels of navigation:
While this sort of transition had worked well for past projects, it didn’t feel quite right for this one. I wanted it to have a little more personality, to feel like it was organically reacting to the item you selected.
I thought it might be cool to stagger the animation, so the selected item began moving first, with its siblings following as if tethered together:
I was happy to pull it off with a modest amount of GSAP and JavaScript ECMAScript.
I started by looping through the items I wanted to animate:
var elements = document.querySelectorAll('.js-MenuItem');
elements.forEach((element, index) => {
// Where the magic happens!
});
Code language: JavaScript (javascript)
Within that loop, I’m creating a new array that groups elements by their distance from the current one. I chose this over a simpler sort because I wanted elements that were the same distance from the selected one to animate at the exact same time. Otherwise, the animation might appear more random than organic.
// Create new array
var elementsByDistance = [];
// Loop through elements again
elements.forEach((thisElement, thisIndex) => {
// Use the magic of math to determine distance
var distance = Math.abs(index - thisIndex);
// Create a group for this distance if it doesn't exist
if (!elementsByDistance[distance]) {
elementsByDistance[distance] = [];
}
// Add element to the group
elementsByDistance[distance].push(thisElement);
});
Code language: JavaScript (javascript)
With that information in hand, we have what we need to pull off the animation on click
using GSAP’s staggerTo
method:
element.addEventListener('click', event => {
// Only necessary if you're using anchor tags
// (to enable hash fallbacks, for example)
event.preventDefault();
// Animate each distance group, with a duration of
// 0.5 seconds and a delay of 0.1 seconds between
TweenMax.staggerTo(elementsByDistance, 0.5, {
x: '-100%',
ease: Back.easeIn.config(1)
}, 0.1);
// Logic for sliding in the next view goes here
});
Code language: JavaScript (javascript)
Voilá! A menu transition with more personality:
The appropriateness of this demo will vary project to project, both in terms of the animation’s emotional impact and its execution. But it’s fun to learn that these oft-overlooked techniques are well within the web’s grasp.