Horizontal Scrolling Section with Pin and Fade Effects
In this tutorial, we’ll build a pin and fade effect using GSAP's ScrollTrigger plugin. This effect is commonly used for interactive, dynamic scrolling sections where the content is "pinned" in place for a moment before fading out, while the next section fades in and slides into view.
Step 1: Import GSAP and ScrollTrigger
The first step is to bring in the required libraries. We're using GSAP and its ScrollTrigger plugin, which allows us to create scroll-based animations.
import gsap from "https://cdn.skypack.dev/gsap";
import { ScrollTrigger } from "https://cdn.skypack.dev/gsap/ScrollTrigger";
// Register the ScrollTrigger plugin
gsap.registerPlugin(ScrollTrigger);
This imports the GSAP animation library from a CDN and registers the ScrollTrigger plugin, which enables us to trigger animations based on scroll position.
Step 2: HTML Structure
Before diving into the code, let’s assume you have an HTML structure like this:
<div id="horizontal-section">
<div class="wrapper">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>
</div>
Here, the #horizontal-section
contains a wrapper
that holds multiple item
elements. These items will be animated as we scroll.
Step 3: Setting Initial States for Items
We want all items except the first one to be positioned outside the viewport, so they slide into view when triggered. We use GSAP's set
function to place each item 100% off-screen (to the right) except for the first one.
// Select the HTML elements needed for the animation
const horizontalSection = document.querySelector("#horizontal-section");
const wrapper = horizontalSection.querySelector(".wrapper");
const items = wrapper.querySelectorAll(".item");
// Set initial positions of items
items.forEach((item, index) => {
if (index !== 0) {
gsap.set(item, { xPercent: 100 });
}
});
gsap.set
: This method sets the initial position of eachitem
. In this case, every item except the first is moved 100% off-screen to the right usingxPercent: 100
.
Step 4: Creating the Pin and Fade Animation with GSAP Timeline
Now, we create a timeline to control the animation of the items as the user scrolls. Each item will fade out and shrink slightly in size, while the next item fades in and slides into view.
function initScroll() {
const tl = gsap.timeline({
scrollTrigger: {
trigger: horizontalSection,
pin: true,
start: "top top",
end: () => `+=${items.length * 100}%`,
scrub: 1,
invalidateOnRefresh: true,
},
defaults: { ease: "none" },
});
// Animate each item
items.forEach((item, index) => {
if (index !== items.length - 1) {
tl.to(item, {
scale: 0.9,
opacity: 0,
}).to(
items[index + 1],
{
xPercent: 0,
},
"<"
);
}
});
}
Breaking Down the Code:
- GSAP Timeline:
- We create a timeline
tl
to manage a series of animations in sequence. - This timeline is connected to ScrollTrigger, which controls the progress of the animations based on the user’s scroll position.
- We create a timeline
- ScrollTrigger Properties:
trigger
: The element that will trigger the scroll animation (in this case,#horizontal-section
).pin: true
: This keeps the section in place while its contents animate. The content will scroll inside this pinned section.start: "top top"
: The animation starts when the top of the section reaches the top of the viewport.end:
+=${items.length * 100}%``: The animation ends after scrolling through all items. The100%
is a relative measure based on the height of the viewport, so this ensures that the animation lasts long enough for all items to fade in and out.scrub: 1
: This creates a smooth, synchronized relationship between the scroll position and the timeline, ensuring that the animations respond to how quickly or slowly the user scrolls.invalidateOnRefresh: true
: Ensures the ScrollTrigger recalculates its start and end positions if the window is resized.
- Animating Items:
- Inside the
forEach
loop, we animate each item in sequence. - The
scale
is reduced to0.9
and theopacity
is faded to0
, making the item shrink and disappear. - At the same time, the next item is animated by setting
xPercent: 0
, bringing it into the viewport from its initial off-screen position. - The
"<"
sign tells GSAP to execute the second animation at the same time as the first one (i.e., while the previous item is fading out, the next one is sliding in).
- Inside the
Step 5: Initialize the Scroll Animations
Finally, we call the initScroll
function to activate the animations.
// Call the function
initScroll();
This runs the timeline and enables the pinning, fading, and sliding effects for your items as you scroll through the section.
Step 6: Customizing the Effects
You can easily tweak this setup for different effects. For example, you could:
- Adjust the
scale
value to control how much the item shrinks. - Change the
opacity
values to create different fade speeds. - Modify the timeline duration by adjusting the percentage in the
end
property of ScrollTrigger. - Add more effects like rotation, blur, or color change during the transitions.
Conclusion
This pin and fade effect is a powerful technique for building smooth, engaging scroll animations. By pinning the section and fading out the current item while sliding the next one in, you can create a seamless transition between content blocks that guides users through your content in an interactive and dynamic way.
With GSAP and ScrollTrigger, the possibilities are endless. These libraries make it easy to animate elements based on scroll position, opening up creative opportunities to enhance user engagement on your website.
Feel free to adjust the values and experiment with different effects to suit your design needs!