Access the AI Animation Generator and premium effects
Upgrade your plan to keep generating animations and unlock premium effects.
Master the world's most powerful animation library with this comprehensive beginner-to-intermediate guide. Learn everything from simple animations to complex sequences and scroll-triggered effects.
gsap.to() is the most fundamental GSAP method. It animates elements FROM their current state TO a target state that you define. Think of it as saying "take this element and animate it to this destination." This method is perfect for creating entrance animations, button interactions, and general movement effects.
The syntax is straightforward: you pass a target (element or selector), then an object containing the properties you want to animate and the duration. GSAP automatically calculates the current value and creates a smooth interpolation to your target value over the specified time.
gsap.to('.demo-box', {
duration: 2,
x: 200, // Move 200px right
y: 100, // Move 100px down
rotation: 360, // Rotate full circle
borderRadius: '50%',
backgroundColor: '#00FF66',
ease: 'power2.inOut'
});
You can animate virtually any CSS property: position (x, y), rotation, scale, opacity, colors, margins, padding, and more. GSAP even has shortcuts like x and
The beauty of gsap.to() is its simplicity and power. A one-liner can create impressive animations. It's the method you'll use most often when building interactive web experiences.
While gsap.to() animates TO a destination, gsap.from() animates FROM a starting point. It's the inverse operation—you define where the element should START, and GSAP animates it to its natural (current) state. This is incredibly useful for entrance animations where you want elements to fade in, slide in, or grow in.
The key difference: gsap.from() immediately sets the properties you define, then animates back to the element's original state. This is perfect for page-load animations where you want elements to animate into their final positions. Unlike CSS animations that require keyframes, gsap.from() is dynamic and can be triggered programmatically.
gsap.from('.demo-box', {
duration: 1.5,
opacity: 0, // Start invisible
y: -50, // Start above
scale: 0.5, // Start smaller
stagger: 0.2, // Stagger each box by 0.2s
ease: 'back.out'
});
A common pattern is combining gsap.from() with stagger to create that popular "staggered entrance" effect where elements animate in one after another. The stagger parameter automatically offsets the animation start time for each element, creating a cascade effect that feels natural and polished.
Sometimes you need complete control over both the starting and ending states. Enter gsap.fromTo(), which lets you explicitly define both the FROM state AND the TO state. This is the most explicit approach and removes any ambiguity about what your animation should do.
gsap.fromTo() takes three parameters: the target element, a vars object for the starting state (fromVars), and another vars object for the ending state (toVars). This method is invaluable when you want pixel-perfect control or when the element's current state is unknown and you want to be explicit about the entire animation range.
gsap.fromTo('.demo-box',
{
// FROM state
x: -100,
opacity: 0,
rotation: -45
},
{
// TO state
x: 100,
opacity: 1,
rotation: 45,
duration: 2,
ease: 'power3.inOut'
}
);
gsap.to(): Current state → Defined end state (implicit start)
gsap.from(): Defined start state → Current state (implicit end)
gsap.fromTo(): Defined start state → Defined end state (explicit both)
Use gsap.fromTo() when you need predictable, repeatable animations regardless of the element's initial state. It's especially useful for component-based animations where you might not know what CSS has already been applied to an element.
You can also use gsap.fromTo() with timeline sequences for maximum control over complex animation sequences where each step needs explicit start and end points.
Not every animation needs motion. Sometimes you just need to instantly change properties without animation. That's where gsap.set() comes in. It's essentially gsap.to() with a duration of 0—it sets properties immediately without any transition.
Why use gsap.set() instead of just changing CSS directly? Because gsap.set() understands GSAP's property names and transforms. It handles transforms, shorts like x/y instead of left/top, and integrates seamlessly with other GSAP methods. It's particularly useful before animations start to reset element states, or in timelines to jump to specific values.
// Click button to randomize
gsap.set('.demo-box', {
x: Math.random() * 150,
y: Math.random() * 150,
backgroundColor: '#' + Math.floor(Math.random()*16777215).toString(16),
rotation: Math.random() * 360
});
// Or use it to reset before an animation
gsap.set('.box', { opacity: 0, y: -20 });
gsap.to('.box', { opacity: 1, y: 0, duration: 1 });
Think of gsap.set() as the "sniper" approach—when you need to hit a specific state instantly without any animation. It's lightweight and perfect for state management in your animations.
Duration isn't everything. An animation that takes 1 second feels completely different depending on how the motion unfolds. Easing (or "easing functions") control the acceleration and deceleration of animation, making movements feel natural, bouncy, elastic, or snappy. GSAP includes dozens of built-in easing functions that transform linear motion into lifelike movement.
The default easing in GSAP is 'power1.inOut', which provides subtle acceleration. But you can get dramatic effects: 'elastic.out' adds a bounce-back effect, 'bounce.out' creates realistic bouncing, 'back.out' overshoots then settles, and 'sine.inOut' creates smooth, organic motion. The right easing choice can make the difference between an animation that feels cheap and one that feels premium.
// Common GSAP easing functions
gsap.to('.box', { x: 200, duration: 2, ease: 'power1.out' });
gsap.to('.box', { x: 200, duration: 2, ease: 'elastic.out' });
gsap.to('.box', { x: 200, duration: 2, ease: 'bounce.out' });
gsap.to('.box', { x: 200, duration: 2, ease: 'back.out' });
// Easing types: in, out, inOut
gsap.to('.box', { x: 200, duration: 2, ease: 'power3.in' }); // Slow start
gsap.to('.box', { x: 200, duration: 2, ease: 'power3.out' }); // Fast start
gsap.to('.box', { x: 200, duration: 2, ease: 'power3.inOut' }); // Both
power1-power4: Smooth acceleration from linear to very pronounced
sine: Smooth, organic motion (like sine waves)
elastic: Bounces back and forth before settling
bounce: Realistic bouncing effect
back: Overshoots target then settles back
Each easing function comes in three variants: '.in' (slow start, fast end), '.out' (fast start, slow end), and '.inOut' (slow start and end). Use '.out' for introductions, '.in' for exits, and '.inOut' for continuous motion. For an interactive easing visualizer, check out our easing guide.
Pro tip: Don't default to linear animations. Even subtle easing makes motion feel intentional and polished. Your users might not consciously notice the easing, but they'll definitely feel the difference in how "right" the animation feels.
Want to animate multiple elements but have them start at slightly different times? That's stagger. Instead of all elements animating simultaneously, stagger offsets the start time of each element by a specified amount, creating a cascading or sequential effect. It's one of GSAP's most powerful features for creating sophisticated motion sequences.
The stagger parameter can be a simple number (the delay between each element) or a complex object with options like 'from' (start direction), 'grid' (for 2D layouts), and 'amount' (total time to spread animations across). This flexibility lets you create everything from simple cascades to complex grid animations.
// Simple stagger: 0.1s delay between each element
gsap.to('.box', {
duration: 0.8,
scale: 1.2,
opacity: 1,
stagger: 0.1
});
// Advanced stagger with configuration
gsap.to('.box', {
duration: 0.8,
y: -20,
opacity: 1,
stagger: {
amount: 0.5, // Spread animation over 0.5 seconds
from: 'center', // Start from center (or 'start', 'end', 'edges')
grid: [4, 2] // 4 columns, 2 rows
}
});
Stagger is commonly used for list animations (product listings, team members), grid layouts, and creating visual interest in entrance sequences. Combined with easing, stagger creates professional-looking animations that would take complex CSS or manual timing to achieve.
Pro tip: Use small stagger values (0.05-0.15s) for subtle effects that feel sophisticated. Larger stagger values are better for longer sequences where the spacing becomes part of the visual rhythm.
When you need to coordinate multiple animations playing in sequence or parallel, timelines are your answer. A timeline is a container that controls the playback of multiple tweens (individual animations). Instead of managing delays manually, timelines handle the orchestration, letting you add animations in the order they should play.
Create a timeline with gsap.timeline(), then add tweens with .to(), .from(), or .fromTo(). By default, tweens are added to the end of the timeline, but you can use position parameters to insert them at specific times, play them in parallel, or create complex sequences. Timelines also give you playback control: play, pause, resume, reverse, and seek to specific points.
// Create timeline
const tl = gsap.timeline();
// Add animations in sequence
tl.to('.box1', { duration: 0.8, x: 100, ease: 'power2.out' })
.to('.box2', { duration: 0.8, y: -50, ease: 'power2.out' })
.to('.box3', { duration: 0.8, rotation: 360, ease: 'back.out' });
// Or add at same time with '<' (at start of previous)
tl.to('.box1', { duration: 1, x: 50 })
.to('.box2', { duration: 1, y: 50 }, '<'); // Parallel
// Timeline controls
tl.play();
tl.pause();
tl.reverse();
tl.seek(1.5); // Jump to 1.5 seconds
Timelines are essential for complex interactions—multi-step animations on click, coordinated movement sequences, and sophisticated page transitions. They eliminate the need for manual delay calculations and make your code more readable and maintainable. For a deep dive, see our complete timeline guide.
You can also create nested timelines, add callbacks at specific points, and even reverse animations entirely. This makes timelines incredibly powerful for interactive experiences where users need to trigger, pause, or reverse complex animation sequences.
GSAP's ScrollTrigger plugin lets you tie animations to scroll position. Instead of animations playing on load or on click, they trigger when elements come into view as the user scrolls. This creates the popular "animate-on-scroll" effect that adds visual interest to long pages and keeps users engaged.
ScrollTrigger works by monitoring an element's position relative to the viewport. When that element enters a specified trigger area, GSAP plays the animation. You can even tie animation progress directly to scroll position, creating "scrubbing" effects where scrolling controls the animation timeline. This is used for parallax effects, progress indicators, and interactive scroll stories.
Scroll down to see the animation trigger
// Basic ScrollTrigger (must register plugin first)
gsap.registerPlugin(ScrollTrigger);
gsap.to('.box', {
duration: 1,
opacity: 1,
y: -50,
scrollTrigger: {
trigger: '.box', // Element to watch
start: 'top 80%', // When trigger top hits 80% of viewport
end: 'top 20%', // Animation end point
markers: true // Debug markers (remove for production)
}
});
// Scrub: tie animation to scroll progress (0-3 = smoothing)
gsap.to('.box', {
duration: 2,
x: 500,
scrollTrigger: {
trigger: '.box',
scroller: window,
scrub: 1 // 1 = 1 second smoothing, true = instant
}
});
ScrollTrigger is incredibly powerful but also complex—there's much more to learn about markers, pinning, multiple triggers, and scroll-driven animations. For comprehensive coverage and interactive examples, check out our ScrollTrigger guide.
Common uses include fade-in animations as users scroll past elements, parallax effects where background moves slower than foreground, and progress indicators that advance as users scroll through content. ScrollTrigger makes these effects performant by only animating when needed, not on every scroll event.
Use transforms (x, y, rotation, scale) instead of top/left/width/height for GPU acceleration. Keep animations under 2-3 seconds to maintain user attention. Avoid animating massive numbers of elements simultaneously.
Respect prefers-reduced-motion for animations. Always ensure animations are supplementary, not essential to content. Provide fallbacks for users with motion sensitivity.
Separate animation logic from DOM interactions. Create reusable animation functions. Use meaningful variable names for timelines and tweens.
Keep animations snappy—too slow feels sluggish, too fast feels jarring. 0.6-1.2 seconds is usually ideal. Use callbacks to sync animations with other events.
Entrance animations use out eases (fast start, slow end). Exit animations use in eases. Continuous motion uses inOut. Bouncy feels playful, power eases feel smooth and professional.
Kill animations when components unmount (React, Vue). Use gsap.killTweensOf() to stop specific animations. Prevent memory leaks in single-page applications.
You've learned the fundamentals of GSAP. From simple tweens to complex timelines and scroll-triggered effects, you have the knowledge to create professional, engaging animations. Now it's time to experiment, build, and create something amazing.