From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
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!