Foundations

What is GSAP?

GSAP (GreenSock Animation Platform) is a professional JavaScript animation library used to create:

  • UI animations
  • Website interactions
  • Scroll animations
  • SVG animations
  • Game animations
  • Product showcases

Official site:

GSAP

Installation

1. Setup & Installation


Pure HTML/CSS/JS

<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>

Vite Vanilla JS

npm create vite@latest
npm install
npm install gsap

Import:

import gsap from "gsap";


Project Setup

Project Setup

<div class="box"></div>


.box {
  width: 100px;
  height: 100px;
  background: red;
}


gsap.to(".box", {
  x: 300
});


Core GSAP

gsap.to()

Animates an element from its current state to a new state.

Syntax

gsap.to(target, {
  property: value,
  duration: time
});

Example

<div class="box"></div>

<script>
gsap.to(".box", {
  x: 300,
  duration: 2
});
</script>

What Happens?

  • Box starts from its current position.
  • Moves 300px right.
  • Takes 2 seconds.


gsap.from()

Animates an element from a given state to its current state.

Syntax

gsap.from(target, {
  property: value,
  duration: time
});

Example

gsap.from(".box", {
  x: -300,
  opacity: 0,
  duration: 2
});

What Happens?

  • Starts 300px left.
  • Invisible initially.
  • Moves to original position.
  • Opacity becomes 1.

Use Cases

  • Page Load Animations
  • Hero Sections
  • Scroll Animations

gsap.fromTo()

Defines both starting and ending values.

Syntax

gsap.fromTo(
  target,
  { startProperties },
  { endProperties }
);

Example


gsap.fromTo(
  ".box",
  {
    x: 0
  },
  {
    x: 500,
    duration: 2
  }
);

4. gsap.set()

Changes properties instantly.

Syntax

gsap.set(target, {
  property: value
});

Example

gsap.set(".box", {
  x: 200,
  opacity: 0.5
});

What Happens?

Immediately:

  • Moves box to x=200
  • Opacity = 0.5
  • No animation

Use Case

Set initial state before animation.

gsap.set(".box", { opacity: 0 });

gsap.to(".box", {
  opacity: 1,
  duration: 2
});


Properties

Properties

GSAP animates many CSS properties.

Position

x: 200
y: 100

Rotation

rotation: 360

Scale

scale: 2

Opacity

opacity: 0.5

Width & Height

width: "300px",
height: "200px"

Color

backgroundColor: "blue"

Example

gsap.to(".box", {
  x: 200,
  rotation: 360,
  scale: 1.5,
  opacity: 0.7,
  duration: 2
});


Easing

Easing

Easing controls animation speed behavior.

Linear

ease: "none"

Constant speed.

---------

Power1

ease: "power1.out"

Starts fast, ends slow.

------___

Power2

ease: "power2.out"

Smoother effect.

gsap.to(".box", {
  x: 300,
  duration: 2,
  ease: "power2.out"
});

Bounce

ease: "bounce.out"

Example

gsap.to(".ball", {
  y: 300,
  duration: 2,
  ease: "bounce.out"
});

Elastic

ease: "elastic.out"

Spring-like effect.

gsap.to(".box", {
  x: 300,
  ease: "elastic.out(1, 0.3)"
});


Repeat

Repeat

Repeats animation multiple times.

Example

gsap.to(".box", {
  x: 300,
  duration: 1,
  repeat: 2
});

Timeline

Run 1
Run 2
Run 3

Because:

repeat: 2

means repeat 2 extra times.


Infinite Repeat

repeat: -1

Example:

gsap.to(".box", {
  rotation: 360,
  duration: 2,
  repeat: -1
});

Infinite rotation.

Yoyo

Makes animation reverse direction after each repeat.

Example

gsap.to(".box", {
  x: 300,
  duration: 1,
  repeat: 3,
  yoyo: true
});

Without Yoyo

→ reset
→ reset
→ reset

With Yoyo

→
←
→
←


Stagger

Animates multiple elements one after another.

HTML

<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>

Example

gsap.to(".box", {
  y: -100,
  duration: 1,
  stagger: 0.3
});

What Happens?

Box1 ---->
      0.3s
Box2 ---->
      0.3s
Box3 ---->
      0.3s
Box4 ---->


Advanced Stagger

gsap.to(".box", {
  y: -100,
  duration: 1,
  stagger: {
    each: 0.2,
    from: "center"
  }
});

Result

Animation starts from center element and spreads outward.

GSAP Timelines

Timelines

Timelines are one of GSAP's most powerful features. Instead of managing multiple animations separately, you can organize them into a sequence.


Why Use Timelines?

Without Timeline:

gsap.to(".box1", {
  x: 200,
  duration: 1
});

gsap.to(".box2", {
  x: 200,
  duration: 1,
  delay: 1
});

gsap.to(".box3", {
  x: 200,
  duration: 1,
  delay: 2
});

Problems:

  • Too many delays
  • Hard to maintain
  • Difficult to synchronize

With Timeline:

const tl = gsap.timeline();

tl.to(".box1", {
  x: 200,
  duration: 1
})
.to(".box2", {
  x: 200,
  duration: 1
})
.to(".box3", {
  x: 200,
  duration: 1
});

Cleaner and easier to control.



Timeline Basics

1. Timeline Basics

A Timeline is a container that holds multiple animations.

Creating a Timeline

const tl = gsap.timeline();

Simple Example

<div class="box red"></div>
<div class="box blue"></div>
<div class="box green"></div>


const tl = gsap.timeline();

tl.to(".red", {
  x: 300,
  duration: 1
})
.to(".blue", {
  x: 300,
  duration: 1
})
.to(".green", {
  x: 300,
  duration: 1
});

Animation Flow

Red   -------->
Blue           -------->
Green                    -------->

Each animation starts after the previous one ends.

Timeline Methods

Timeline Methods

.to()

tl.to(".box", {
  x: 200,
  duration: 1
});

.from()

tl.from(".box", {
  opacity: 0,
  y: 100,
  duration: 1
});

.fromTo()

tl.fromTo(
  ".box",
  { scale: 0 },
  { scale: 1, duration: 1 }
);

.set()

tl.set(".box", {
  opacity: 0
});

Instant property change.

Labels

Labels are named positions inside a timeline.

Instead of using time values, you can use meaningful names.

Adding Labels

tl.addLabel("start");

or

tl.addLabel("intro", 2);

Example

const tl = gsap.timeline();

tl.addLabel("begin")

.to(".box1", {
  x: 200,
  duration: 1
})

.addLabel("middle")

.to(".box2", {
  x: 200,
  duration: 1
})

.addLabel("end");

Timeline:

begin ---- box1 ---- middle ---- box2 ---- end


Position Parameters

Position parameters control WHEN animations start.

This is one of the most important Timeline concepts.

Default

tl.to(".box1", {
  x: 200,
  duration: 1
});

tl.to(".box2", {
  x: 200,
  duration: 1
});

Result:

Box1 ---->
Box2         ---->

Sequential.

Absolute Time

tl.to(".box1", {
  x: 200
}, 2);

Starts at 2 seconds.

Relative Position "+=1"

tl.to(".box2", {
  x: 200
}, "+=1");

Starts 1 second after previous animation ends.

Timeline:

Box1 ---->
          (1s gap)
Box2               ---->

Relative Position "-=0.5"

tl.to(".box2", {
  x: 200
}, "-=0.5");

Starts 0.5s before previous animation ends.

Timeline:

Box1 -------->
        Box2 -------->

Overlap created.


Start Together

tl.to(".box1", {
  x: 200
})
.to(".box2", {
  y: 200
}, "<");

"<" means start at same time as previous animation.

Timeline:

Box1 -------->
Box2 -------->

Both together.


Start After Previous Starts

tl.to(".box1", {
  x: 200
})
.to(".box2", {
  y: 200
}, "<0.5");

Starts 0.5 seconds after previous starts.

End Together

tl.to(".box1", {
  duration: 2
})
.to(".box2", {
  duration: 1
}, ">");

">" means start after previous animation ends.

Timeline Control

Timeline Control

Timelines can be controlled like videos.

Play

tl.play();

Starts timeline.

Pause

tl.pause();

Stops at current position.

Resume

tl.resume();

Continues from pause point.

Restart

tl.restart();

Starts from beginning.

Reverse

tl.reverse();

Plays backwards.

Seek

Jump to specific position.

tl.seek(2);

Move to 2 seconds.

Seek to Label

tl.seek("intro");

Progress

tl.progress(0.5);

Moves timeline to 50%.

Time Scale

Controls playback speed.

Faster

tl.timeScale(2);

2x speed.

Slower

tl.timeScale(0.5);

Half speed.

Example: Button Controls

<button id="play">Play</button>
<button id="pause">Pause</button>
<button id="reverse">Reverse</button>


document
.getElementById("play")
.addEventListener("click", () => tl.play());

document
.getElementById("pause")
.addEventListener("click", () => tl.pause());

document
.getElementById("reverse")
.addEventListener("click", () => tl.reverse());


GSAP ScrollTrigger

GSAP ScrollTrigger

ScrollTrigger is a GSAP plugin that lets you animate elements based on the user's scroll position.

What is ScrollTrigger?

Normally animations run automatically:

gsap.to(".box", {
  x: 300,
  duration: 2
});

With ScrollTrigger, animations start when the user scrolls to a specific point.

gsap.to(".box", {
  x: 300,
  scrollTrigger: ".box"
});


Install ScrollTrigger

CDN

<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js"></script>

Register Plugin

gsap.registerPlugin(ScrollTrigger);


1. Trigger

The trigger is the element that starts the animation.

Basic Syntax

gsap.to(".box", {
  x: 300,

  scrollTrigger: {
    trigger: ".box"
  }
});

Flow

User Scrolls
      ↓
Trigger Reaches Viewport
      ↓
Animation Starts

Example

<section class="section">
  <div class="box"></div>
</section>


gsap.to(".box", {
  rotation: 360,

  scrollTrigger: {
    trigger: ".section"
  }
});

Animation starts when .section enters viewport.


2. Start & End

Control exactly when animation starts and stops.

Start

start: "top center"

Meaning:

Element Top
      ↓
Viewport Center

Animation starts when element's top reaches viewport center.

Syntax

start: "elementPosition viewportPosition"



Example

scrollTrigger: {
  trigger: ".box",
  start: "top 80%"
}

Start when box reaches 80% of viewport.

End

end: "bottom center"

Animation ends when:

Element Bottom
      ↓
Viewport Center

Example

scrollTrigger: {
  trigger: ".box",
  start: "top center",
  end: "bottom center"
}


3. Scrub

Scrub links animation progress directly to scrolling.

Without scrub:

gsap.to(".box", {
  x: 500,

  scrollTrigger: {
    trigger: ".box"
  }
});

Animation plays once triggered.

With scrub:

gsap.to(".box", {
  x: 500,

  scrollTrigger: {
    trigger: ".box",
    scrub: true
  }
});

Animation follows scrollbar.

Visual

Scroll 20% → Animation 20%

Scroll 50% → Animation 50%

Scroll 100% → Animation 100%

Smooth Scrub

scrub: 2

Meaning:

Animation catches up smoothly over 2 seconds.

scrollTrigger: {
  trigger: ".box",
  scrub: 2
}


Horizontal Scroll

Horizontal Scroll

Create horizontal scrolling sections.

HTML

<div class="container">
  <section class="panel red"></section>
  <section class="panel blue"></section>
  <section class="panel green"></section>
</div>

CSS

.container {
  display: flex;
  width: 300vw;
}

.panel {
  width: 100vw;
  height: 100vh;
}

GSAP

let sections =
gsap.utils.toArray(".panel");

gsap.to(sections, {
  xPercent: -100 * (sections.length - 1),

  ease: "none",

  scrollTrigger: {
    trigger: ".container",
    pin: true,
    scrub: 1,
    end: "+=3000"
  }
});

Result

Scroll Down

Panel 1 → Panel 2 → Panel 3

Instead of vertical movement.



let sections =
gsap.utils.toArray(".panel");

Converts all panels into an array.

[
  redPanel,
  bluePanel,
  greenPanel
]


gsap.to(sections, {

Animate all panels.

xPercent

xPercent: -100 * (sections.length - 1),

Let's calculate.

We have:

sections.length = 3

Therefore:

-100 * (3 - 1)

= -200

Result:

xPercent: -200

Why -200?

Initially:

[Red][Blue][Green]
 ^
 Visible

After moving:

[Red][Blue][Green]
             ^
 Visible

Need to move:

100% for Blue
100% for Green

Total:

200%

Hence:

xPercent: -200

Negative means move left.

ease

ease: "none"

No acceleration.

Required for smooth scroll syncing.

ScrollTrigger

scrollTrigger: {

Creates scroll-based animation.

Trigger

trigger: ".container",

Animation begins when container reaches viewport.

Pin

pin: true,

Pins container.

Normal scrolling:

Scroll ↓

Section passes away

Pinned:

Scroll ↓

Section stays fixed

This allows horizontal movement while page is still scrolling vertically.

Scrub

scrub: 1,

Links animation to scrollbar.

Without scrub:

Trigger
 ↓
Animation plays automatically

With scrub:

Scroll 20% → Animation 20%

Scroll 50% → Animation 50%

Scroll 80% → Animation 80%

Perfect synchronization.

End

end: "+=3000"

Meaning:

Continue animation
for 3000px of scrolling

Why Need End?

Without enough scroll distance:

Scroll
 ↓
Animation ends too fast

With:

end: "+=3000"

User gets enough space to see:

Red → Blue → Green

Final Flow

Page Scrolls

      ↓

Container Reaches Screen

      ↓

Pin Activated

      ↓

Vertical Scroll Continues

      ↓

Panels Move Horizontally

      ↓

Red → Blue → Green

      ↓

End Reached

      ↓

Pin Released


Parallax

Parallax

Parallax creates depth by moving elements at different speeds.

Example

Background moves slower.

gsap.to(".bg", {
  y: -200,

  scrollTrigger: {
    trigger: ".section",
    scrub: true
  }
});

Foreground

gsap.to(".content", {
  y: -50,

  scrollTrigger: {
    trigger: ".section",
    scrub: true
  }
});

Effect

Background  ← Slow

Foreground  ← Fast

Creates 3D depth illusion.

Image Parallax

gsap.to(".image", {
  yPercent: -20,

  scrollTrigger: {
    trigger: ".image",
    scrub: true
  }
});