JavaScript Animation - GSAP and ScrollTrigger
Gain Extensive Insight into GSAP, ScrollTrigger, and Popular Animation Libraries
By Code Subtle
GSAP in Detail
1. What is GSAP
GSAP (GreenSock Animation Platform) is a powerful JavaScript animation library that enables developers to create smooth, high-performance animations with minimal code. It provides exceptional browser compatibility and easily handles complex animation sequences, making it the preferred choice for professional web animators and developers who need precise control over their animations.
GSAP revolutionizes web animation by offering a robust API that works consistently across all major browsers, eliminating the headaches associated with CSS animations and native JavaScript implementations. In real life, GSAP is used in award-winning websites, interactive landing pages, and sophisticated web applications where fluid motion and engaging user experiences are essential.
Where to use in real life:
Interactive product showcases on e-commerce platforms
Engaging storytelling websites with scroll-based animations
Mobile app onboarding experiences
Data visualization animations
Video game interfaces and menu transitions
2. How to Connect GSAP CDN in JavaScript File
You can easily incorporate GSAP into your project via CDN by adding script tags to your HTML file. This approach requires no installation or build tools, making it accessible for beginners while still being robust enough for production environments.
For production websites, you should consider using specific GSAP version numbers to ensure consistency across deployments, rather than relying on the latest version which might introduce unexpected changes. GSAP's CDN is hosted on reliable servers, ensuring fast loading times and high availability for your animations worldwide.
Syntax:
<!-- Add to the head or end of body in your HTML file -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
Example 1:
<!DOCTYPE html>
<html>
<head>
<title>Code Subtle's GSAP Demo</title>
</head>
<body>
<div class="box"></div>
<!-- Loading GSAP from CDN at the end of body -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>
Example 2:
<!-- Code Subtle's approach for loading multiple GSAP plugins -->
<!DOCTYPE html>
<html>
<head>
<title>Advanced GSAP Setup</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
</head>
<body>
<!-- Content here -->
</body>
</html>
Tips and Tricks:
Always place GSAP script tags before your custom JavaScript to ensure GSAP is loaded before you try to use it
Check the console for any loading errors by typing
console.log(gsap)
- it should return the GSAP objectFor better performance on large projects, consider loading only the GSAP plugins you need rather than the full library
3. Working of GSAP
3.1 gsap.to()
The gsap.to
()
method animates elements from their current state to a specified end state, making it ideal for transitions that start from the element's natural position. This method is the most commonly used GSAP function and forms the foundation of most animation sequences.
It accepts parameters for duration, easing functions, and a wide range of CSS properties and transforms, allowing precise control over how elements move, scale, rotate, and change appearance. In real-world applications, gsap.to
()
is perfect for button hover effects, menu transitions, and introducing elements that are already in the viewport.
Syntax:
gsap.to(target, {
duration: timeInSeconds,
property1: value1,
property2: value2,
ease: "easing-function",
onComplete: callbackFunction
});
Example 1:
// Code Subtle's simple box animation
const box = document.querySelector('.box');
gsap.to(box, {
duration: 2,
x: 200,
y: 100,
backgroundColor: "purple",
rotation: 45,
ease: "power2.inOut"
});
Example 2:
// Code Subtle's text reveal animation
const headings = document.querySelectorAll('h2');
gsap.to(headings, {
duration: 1.5,
opacity: 1,
y: 0,
stagger: 0.2,
ease: "back.out(1.7)"
});
Example 3:
// Code Subtle's button hover effect
const button = document.querySelector('.cta-button');
button.addEventListener('mouseenter', () => {
gsap.to(button, {
duration: 0.3,
scale: 1.1,
backgroundColor: "#ff6b6b",
ease: "power1.out"
});
});
button.addEventListener('mouseleave', () => {
gsap.to(button, {
duration: 0.3,
scale: 1,
backgroundColor: "#4d4dff",
ease: "power1.out"
});
});
Tips and Tricks:
Use the
overwrite: true
property when you have multiple animations targeting the same properties to prevent conflictsThe
ease
parameter dramatically affects the feel of your animation - experiment with different options from GSAP's extensive easing libraryFor complex animations, store your animation in a variable so you can control it later with methods like pause(), play(), or reverse()
3.2 gsap.from()
The gsap.from()
method animates elements from a specified starting state to their current natural state, making it perfect for entrance animations. This approach is particularly useful for introducing elements into a scene as they appear to come from off-screen, grow from nothing, or fade into view.
Unlike gsap.to
()
, which requires you to know the end state, gsap.from()
lets you define where elements should start from before they settle into their normal position in the layout. In real life, gsap.from()
is commonly used for page load animations, revealing content as users scroll down, and animating elements entering from different directions.
Syntax:
gsap.from(target, {
duration: timeInSeconds,
property1: startValue1,
property2: startValue2,
ease: "easing-function",
onComplete: callbackFunction
});
Example 1:
// Code Subtle's entrance animation
const hero = document.querySelector('.hero-section');
gsap.from(hero, {
duration: 1.5,
y: 100,
opacity: 0,
ease: "power3.out"
});
Example 2:
// Code Subtle's staggered card reveal
const cards = document.querySelectorAll('.card');
gsap.from(cards, {
duration: 0.8,
scale: 0.5,
opacity: 0,
y: 50,
stagger: 0.15,
ease: "back.out(1.7)"
});
Example 3:
// Code Subtle's split text animation
const title = document.querySelector('.split-text');
const characters = title.textContent.split("");
title.innerHTML = "";
characters.forEach(char => {
title.innerHTML += `<span>${char}</span>`;
});
const spans = title.querySelectorAll('span');
gsap.from(spans, {
duration: 0.5,
opacity: 0,
y: 20,
rotationX: 90,
stagger: 0.03,
ease: "power1.out"
});
Tips and Tricks:
Use
gsap.from()
for entrance animations andgsap.to
()
for exit animations to maintain intuitive animation logicCombine
opacity
with movement for more natural-looking entrancesFor performance, avoid animating
top
,left
,right
, orbottom
properties - usex
andy
instead which use CSS transforms
GSAP scroll trigger:
3.3 gsap.timeline() - stagger
GSAP's Timeline feature allows developers to sequence multiple animations with precise control over timing, creating complex, choreographed animation sequences with minimal code. Timelines provide a container for animations, enabling them to play in sequence or overlap based on position parameters like "+=0.5" or "-=0.2".
The stagger property within timelines creates visually appealing sequential animations across multiple elements, perfect for lists, grids, or any collection of similar elements. In real-world applications, timelines are used for storytelling websites, complex UI transitions, multi-step animations in games, and creating engaging product reveals.
Syntax:
const tl = gsap.timeline({
defaults: { duration: 1, ease: "power1.out" },
repeat: 0,
yoyo: false,
onComplete: callbackFunction
});
tl.to(target1, { properties })
.from(target2, { properties }, position)
.fromTo(target3, { startProperties }, { endProperties }, position);
Example 1:
// Code Subtle's sequential animation
const tl = gsap.timeline({defaults: {duration: 0.8, ease: "power1.out"}});
tl.from(".logo", {y: -50, opacity: 0})
.from(".menu", {x: 30, opacity: 0}, "+=0.2")
.from(".hero-title", {y: 100, opacity: 0}, "-=0.1")
.from(".hero-subtitle", {y: 20, opacity: 0})
.from(".cta-button", {scale: 0.5, opacity: 0}, "+=0.2");
Example 2:
// Code Subtle's staggered grid animation
const boxes = document.querySelectorAll('.grid-item');
const tl = gsap.timeline();
tl.from(boxes, {
duration: 0.8,
opacity: 0,
scale: 0,
y: 20,
stagger: {
each: 0.1,
grid: [5, 3],
from: "center",
ease: "power2.out"
}
});
Example 3:
// Code Subtle's interactive timeline with controls
const tl = gsap.timeline({paused: true});
tl.to(".circle", {duration: 1, x: 200})
.to(".circle", {duration: 0.75, y: 100}, "+=0.25")
.to(".circle", {duration: 1.25, scale: 2, backgroundColor: "orange"})
.to(".circle", {duration: 1, rotation: 360, borderRadius: "0%"});
// Control buttons
document.querySelector('.play-btn').addEventListener('click', () => tl.play());
document.querySelector('.pause-btn').addEventListener('click', () => tl.pause());
document.querySelector('.reverse-btn').addEventListener('click', () => tl.reverse());
document.querySelector('.restart-btn').addEventListener('click', () => tl.restart());
Tips and Tricks:
Use labels in your timeline (e.g.,
tl.add("label-name")
) to create reference points you can jump to laterThe position parameter (like "+=0.5" or "-=0.2") controls whether animations overlap or wait for previous ones to complete
For complex animations, consider organizing them into smaller timelines that you can nest inside a master timeline for better code organization
ScrollTrigger In Details
1. What is ScrollTrigger
ScrollTrigger is a powerful GSAP plugin that creates scroll-based animations with minimal code, allowing developers to trigger animations as users scroll through a webpage. It provides precise control over when animations start, end, and how they progress based on the user's scroll position, enabling impressive scroll-driven experiences.
Unlike basic scroll event listeners, ScrollTrigger handles all the complex calculations and optimizations behind the scenes, resulting in smooth, performance-friendly animations that work consistently across devices. In real-world applications, ScrollTrigger powers engaging storytelling websites, product showcases, interactive infographics, and portfolio sites where content reveals as the user scrolls.
Where to use in real life:
Long-form storytelling websites
Product feature reveal sections
Portfolio websites with scroll-based transitions
Interactive timelines and infographics
Parallax scrolling effects
E-commerce product showcases
2. How to Connect ScrollTrigger CDN in JS File
To implement ScrollTrigger animations, you must first include both the core GSAP library and the ScrollTrigger plugin via CDN. The order of script loading is critical, as ScrollTrigger depends on the core GSAP functionality being available before it initializes.
After loading both scripts, you need to register the plugin with GSAP using gsap.registerPlugin(ScrollTrigger)
to make the ScrollTrigger functionality available for use in your animations. For production websites, using specific version numbers ensures consistent behavior across deployments and prevents unexpected issues from library updates.
Syntax:
<!-- Add to your HTML file -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
<script>
// Register the plugin
gsap.registerPlugin(ScrollTrigger);
</script>
Example 1:
<!DOCTYPE html>
<html>
<head>
<title>Code Subtle's ScrollTrigger Demo</title>
<!-- Load GSAP and ScrollTrigger in head -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
</head>
<body>
<div class="section"></div>
<script>
gsap.registerPlugin(ScrollTrigger);
// Now ScrollTrigger is ready to use
</script>
</body>
</html>
Tips and Tricks:
Always check that ScrollTrigger is properly registered by adding
console.log(ScrollTrigger)
to see if it returns the ScrollTrigger objectIf you're using webpack or another bundler, you can import ScrollTrigger and register it in your JavaScript files directly
Make sure your ScrollTrigger version matches your GSAP version to avoid compatibility issues
3. Working of ScrollTrigger
3.1 scrollTrigger Object in GSAP
The ScrollTrigger object is integrated into GSAP animations as a configuration object that defines when and how animations respond to scrolling. This powerful system allows animations to start, stop, or progress based on the user's scroll position relative to specific elements on the page.
ScrollTrigger can be used directly within a GSAP animation (like gsap.to
()
) or created independently and referenced by multiple animations, providing exceptional flexibility and control. In real-world applications, the scrollTrigger object powers product feature reveals, parallax effects, and sections that transform as users scroll through content.
Syntax:
// Basic syntax within an animation
gsap.to(target, {
properties: values,
scrollTrigger: {
trigger: element,
start: "top center",
end: "bottom center",
scrub: true,
markers: true,
toggleActions: "play pause reverse reset"
}
});
// Create standalone ScrollTrigger
ScrollTrigger.create({
trigger: element,
start: "top center",
onEnter: () => animation.play(),
onLeave: () => animation.pause()
});
Example 1:
// Code Subtle's basic scroll animation
gsap.to(".animated-box", {
x: 300,
rotation: 360,
duration: 2,
scrollTrigger: {
trigger: ".animated-box",
start: "top center",
end: "bottom center",
scrub: true,
markers: true
}
});
Example 2:
// Code Subtle's toggle class approach
ScrollTrigger.create({
trigger: ".reveal-section",
start: "top 80%",
end: "top 20%",
markers: true,
toggleClass: {
targets: ".reveal-section",
className: "active"
},
onEnter: () => console.log("Section entered viewport"),
onLeave: () => console.log("Section left viewport")
});
Example 3:
// Code Subtle's timeline with ScrollTrigger
const tl = gsap.timeline({
scrollTrigger: {
trigger: ".process-section",
start: "top center",
end: "+=300",
scrub: 0.5,
pin: true,
markers: true
}
});
tl.from(".step-1", {opacity: 0, y: 50})
.from(".step-2", {opacity: 0, y: 50})
.from(".step-3", {opacity: 0, y: 50});
Tips and Tricks:
When debugging, always start with
markers: true
to visualize the trigger pointsFor smoother animations, use decimal values with
scrub
(likescrub: 0.5
) instead of justtrue
Remember that
pin: true
fixes elements in place during the animation, which can dramatically improve the user experience for step-by-step content
3.2 Trigger, Scroller, Marker, Start, End, Scrub
The core functionality of ScrollTrigger is controlled through its configuration properties, with trigger, scroller, markers, start, end, and scrub being the most essential parameters that define how scroll-based animations behave. These properties precisely control when animations begin, how they progress, and when they end based on the scroll position.
Each property serves a specific purpose: trigger defines the reference element, start and end determine the scroll positions that trigger animation states, markers provide visual debugging tools, scroller specifies the scrollable container, and scrub links animation progress to scroll position. In real-world projects, mastering these properties allows developers to create sophisticated scroll experiences that respond naturally to user interaction.
Where to use in real life:
Product feature reveals that animate as users scroll down the page
Storytelling websites where content appears sequentially
Portfolio projects that transform as they enter the viewport
Parallax effects where elements move at different speeds
Interactive infographics that reveal data points as users scroll
Parameters explained:
trigger: The element that triggers the animation when scrolled to
scroller: The element that contains the scrollbar (default is viewport)
markers: Visual indicators showing trigger points (for development)
start: Position where the animation begins ("top bottom" means when top of trigger meets bottom of viewport)
end: Position where the animation completes
scrub: Links animation progress to scroll position (true/false or time value)
Example 1:
// Code Subtle's basic configuration
gsap.to(".feature-image", {
y: 100,
opacity: 1,
duration: 1,
scrollTrigger: {
trigger: ".feature-section",
start: "top 80%", // When top of trigger reaches 80% down the viewport
end: "center center", // When center of trigger reaches center of viewport
scrub: 0.5, // Smooth scrubbing effect
markers: true // Show markers during development
}
});
Example 2:
// Code Subtle's custom scroller setup
const panel = document.querySelector(".horizontal-scroll");
gsap.to(".slider", {
x: -1000,
scrollTrigger: {
trigger: ".slider",
scroller: ".horizontal-scroll", // Custom scrolling container
pin: true,
start: "center center",
end: "+=1000",
scrub: 1,
markers: true
}
});
Example 3:
// Code Subtle's advanced marker configuration
gsap.from(".product-features li", {
y: 50,
opacity: 0,
stagger: 0.1,
scrollTrigger: {
trigger: ".product-features",
start: "top 70%",
end: "bottom 50%",
markers: {
startColor: "green",
endColor: "red",
fontSize: "12px",
indent: 20
},
toggleActions: "play pause reverse reset" // play on enter, pause on leave, etc.
}
});
Tips and Tricks:
Use percentages in start/end values (like "top 80%") for responsive designs that work across screen sizes
The four values in
toggleActions
control what happens when entering, leaving, re-entering, and re-leaving the trigger zoneWhen working with horizontal scrolling, remember to set the proper scroller element and adjust start/end values accordingly