Skip to main content

Fun with Staggered Transitions

By Tyler Sticka

Published on December 12th, 2016

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.