Consecutive Scroll Animations with One Element


Ivan Gorbunov designed a beautiful concept a while ago where this one element gets animated throughout different layouts:

This made me wonder how simple it would be to animate an element across various waypoints while scrolling, making it adapt to the spots using GSAP’s Flip.

It turns out there’s a very helpful GSAP demo that demonstrates this perfectly: GSAP ScrollTrigger Consecutive Scrub Flips. So this is basically showing how to create a consecutive flip animation with ScrollTrigger and scrubbing.

See the Pen
GSAP ScrollTrigger Consecutive Scrub Flips by GSAP (@GreenSock)
on CodePen.

I went ahead and created a little demo with a fancier look, so here is an exploration of that concept.

In our HTML we set the main element to be a div with class “one”:

<section class="content content--inital">
  <div class="one" style="background-image:url(img/main.jpg)"></div>
</section>

In the consecutive sections we define a placeholder element (“content__img”) and style the layout with that element in mind. We also give that element a data-attribute called “data-step” which will serve as indicator that this is an element we want to use as waypoint in our JavaScript:

<section class="content content--center content--blend">
  <div data-step class="content__img"></div>
  <h1 class="content__title font-alt"><span>Seraph</span><br><span>Kamos</span></h1> 
</section>
// Create a GSAP timeline with ScrollTrigger for the Flip animation
const tl = gsap.timeline({
  scrollTrigger: {
    trigger: parentElement, // Trigger animation based on the parent element
    start: 'clamp(center center)', // Start animation when parent is in the center of the viewport
    endTrigger: stepElements[stepElements.length - 1], // End at the last step element
    end: 'clamp(center center)', // End animation when the last step is centered
    scrub: true, // Synchronize animation with scroll
    immediateRender: false
  }
});
// Add Flip animations to the timeline for each state
states.forEach((state, index) => {
  const customFlipConfig = {
    ...flipConfig,
    ease: index === 0 ? 'none' : flipConfig.ease // Use 'none' easing for the first step
  };
  tl.add(Flip.fit(oneElement, state, customFlipConfig), index ? '+=0.5' : 0);
});

Check out the code for the other bits and have fun exploring and playing around with this!

Thanks for checking by!

Recent Articles

Related Stories

Leave A Reply

Please enter your comment!
Please enter your name here