Fun with Staggered Transitions

Written by Tyler Sticka on

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:

All menu items animating together.

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:

The second menu item is tapped, so it animates first, followed by its closest siblings.

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!


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

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)

  // 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

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.

Tyler Sticka

Tyler Sticka is Cloud Four's VP of Design, allowing him to think about design systems every day. When he isn’t directing his team, sketching on sticky notes or nitpicking CSS, he enjoys reading comics, making video games and listening to weird music. He tweets as @tylersticka.

Never miss an article!

Get Weekly Digests

Let’s discuss your project! Email Us