Skip to main content
March 23, 2026Dan Rodney/8 min read

GreenSock: Parallax Animation

Master Dynamic Parallax Effects with GSAP ScrollTrigger

Core Technologies You'll Master

GSAP Animation Library

Professional-grade JavaScript animation framework trusted by top developers. Powers smooth, performant animations with minimal code.

ScrollTrigger Plugin

Advanced scroll-based animation control system. Enables precise timing and coordination of visual effects during user scroll interactions.

CSS Positioning & Layering

Advanced layout techniques using fixed positioning, z-index stacking, and viewport units for immersive visual experiences.

Topics Covered in This JavaScript Tutorial:

Setting up the HTML structure, styling the parallax layers for optimal performance, adding depth data attributes, and implementing GSAP's ScrollTrigger to create smooth parallax animations

Exercise Preview

preview parallax

Exercise Overview

In this hands-on exercise, you'll master the art of creating compelling parallax scrolling animations that enhance user engagement and create memorable web experiences. This technique has become a cornerstone of modern web design, used extensively by leading brands and agencies to create immersive storytelling experiences.

What is Parallax & How Does It Work?

Parallax is a sophisticated visual effect where multiple layers move at different velocities during scroll, creating a convincing sense of three-dimensional depth. This technique mimics how our eyes naturally perceive depth in the real world.

The secret to professional parallax lies in layering—you need a minimum of three distinct layers positioned at different virtual distances from the viewer. Background elements move slowly (simulating distance), while foreground elements move rapidly (simulating proximity). This differential movement creates the illusion of spatial depth that captivates users and encourages longer page engagement.

While the JavaScript implementation is straightforward, the most challenging aspect of parallax development is typically the image preparation in Photoshop. Professional parallax requires meticulous layer separation and transparency work. We've handled this preprocessing for you, but in production environments, you'll need each layer isolated with transparent backgrounds, saved as PNG files to maintain alpha channel information. Here's how our three-layer composition breaks down (background.jpg, middleground.png, and foreground.png):

parallax layers

Notice how each layer contains distinct visual elements that will move independently, creating depth through motion differential.

Parallax Effect Fundamentals

1

Layer Creation

Multiple image layers are stacked with transparent backgrounds using PNG format to maintain visual clarity

2

Speed Differentiation

Each layer moves at different speeds - background layers slower, foreground layers faster to simulate depth

3

Depth Perception

The varying movement speeds create convincing 3D depth illusion that engages users during scroll interactions

Professional Insight

The most challenging aspect of parallax development is the Photoshop preparation work. Each layer requires precise background removal and transparent PNG export for seamless layering effects.

Getting Started

  1. Navigate to the GSAP-Parallax folder located in Desktop > Class Files > JavaScript Class. Open this entire folder in your code editor (Visual Studio Code, Sublime Text, or your preferred environment) to access all project assets efficiently.
  2. In your code editor, open index.html from the GSAP-Parallax folder to examine the starter markup.
  3. Launch index.html in your browser for initial preview.

    • You'll see a static background image with a heading positioned below it—this represents our foundation layer.
    • Our task is to overlay the transparent middleground and foreground images, then reposition the heading to create a cohesive layered composition.
  4. Keep the browser tab open for live reloading as we make modifications.

Now that we have our development environment configured, let's build the HTML structure that will support our parallax animation.

Setting up the HTML

  1. In your code editor, locate the hero div containing our initial markup:

    <div id="hero">
       <img src="img/background.jpg">
       <h1>The Islands of Hawaii</h1>
    </div>
  2. Add the remaining parallax layers by duplicating the image element and updating the src attributes. This creates our complete layer stack:

    <div id="hero">
       <img src="img/background.jpg">
       <img src="img/middleground.png">
       <img src="img/foreground.png">
       <h1>The Islands of Hawaii</h1>
    </div>
  3. Save your changes and refresh the browser.

    • Scroll down to observe all three images stacked vertically—they're currently in normal document flow.
    • Next, we'll use CSS positioning to overlay these layers in the same spatial location, creating our foundation for the parallax effect.

With our HTML structure complete, we need to style these layers for proper positioning and visual hierarchy.

Parallax Layer Structure

Background Layer
1
Middleground Layer
2
Foreground Layer
3

Styling the Parallax Layers

  1. In your code editor, open main.css from the css folder to begin styling our parallax container.
  2. Above the existing #content rule, add this container styling to make our hero section fill the viewport:

    #hero {
       height: 100vh;
    }
  3. Below the #hero rule, add this universal styling that positions all child elements in the same location with full viewport coverage:

    #hero * {
       height: 100vh;
       width: 100%;
       position: fixed;
       object-fit: cover;
    }

    NOTE: The * wildcard selector targets all child elements efficiently. The object-fit: cover; property provides the same proportional scaling behavior as background-size: cover; but works on regular img elements, ensuring our images maintain aspect ratio while filling the container.

  4. Save your changes and refresh the browser.

    • The layers now stack properly, but you'll notice scrolling is disabled and the heading appears at the top of the viewport.
    • This behavior is expected—GSAP will restore scroll functionality when we implement the animation system.
    • Let's reposition the heading for better visual hierarchy.

Our layers are now properly stacked, but we need to optimize the heading placement for better visual impact.

CSS Viewport Units

Using 100vh ensures the hero section fills the entire viewport height, creating an immersive full-screen experience that adapts to any device screen size.

Fixed Positioning Approach

Pros
Creates seamless layer stacking effect
Enables smooth scroll-based animations
Maintains consistent viewport coverage
Works across different screen sizes
Cons
Initially disables normal page scrolling
Requires JavaScript to restore scroll functionality
Can impact accessibility if not implemented properly

Positioning the Heading at the Bottom

  1. Below the #hero * rule, add this flexbox positioning to anchor the heading at the bottom of the viewport:

    #hero h1 {
       display: flex;
       align-items: flex-end;
       justify-content: center;
       padding-bottom: 15vh;
    }
  2. Save and refresh to verify the heading now sits prominently at the bottom of the viewport.

    • The 15vh bottom padding provides comfortable spacing from the viewport edge while maintaining responsive behavior.
    • With our visual composition finalized, we can implement the animation system.

Now we need to provide depth information that GSAP can use to calculate movement speeds for each layer.

Adding the Depth Info

GSAP's parallax system requires depth values for each layer to calculate relative movement speeds. We'll use HTML5 data attributes—a standardized method for embedding custom data that JavaScript can access. Elements with lower depth values will move slower (appearing distant), while higher values will move faster (appearing closer).

  1. In index.html, add the data-depth attributes to each parallax element:

    <div id="hero">
       <img data-depth="0.25" src="img/background.jpg">
       <img data-depth="0.5" src="img/middleground.png">
       <img data-depth="1" src="img/foreground.png">
       <h1 data-depth="1.5">The Islands of Hawaii</h1>
    </div>

    NOTE: These data-depth values create a progression from background (0.25) to foreground (1.5). A value of 0 would create no movement, while higher numbers produce faster animation. You can fine-tune these values to achieve your desired visual effect—the numbers represent animation multipliers rather than fixed units.

With our depth data in place, we can now implement the GSAP animation system that will bring our parallax effect to life.

Data Depth Values Explained

FeatureLayerDepth ValueMovement Speed
Background0.25Slowest
Middleground0.5Medium
Foreground1.0Fast
Heading1.5Fastest
Recommended: Higher values create faster movement, simulating objects closer to the viewer

Using GSAP to Make the Parallax Work

  1. Include the required GSAP libraries just before the closing </body> tag. These provide the core animation engine and scroll-triggered animation capabilities:

    <script src="js/gsap.min.js"></script>
       <script src="js/ScrollTrigger.min.js"></script>
    </body>
  2. Add our custom parallax script that leverages GSAP's power:

    <script src="js/gsap.min.js"></script>
       <script src="js/ScrollTrigger.min.js"></script>
       <script src="js/parallax.js"></script>
    </body>
  3. Save your HTML file before configuring the JavaScript.
  4. Open parallax.js from the js folder to examine the animation code.

    This optimized parallax implementation was created by Jack Doyle, GSAP's founder, and shared with the development community. It handles performance optimization, scroll calculations, and responsive behavior automatically.

  5. Update the trigger selector to target our hero container:

    const tl = gsap.timeline({
       scrollTrigger: {
       trigger: "#hero", 
  6. Update the element selector to target our parallax layers:

    gsap.utils.toArray("#hero *").forEach(layer => {
  7. Save and close the JavaScript file.
  8. Refresh your browser and test the parallax effect.

    • Scroll down slowly to observe how each layer moves at its designated speed—the background crawls while the heading races.
    • You'll notice some visual issues: background edges become visible, and the parallax layers obscure lower page content.
    • These are common implementation challenges we'll resolve with proper layering.

Our parallax animation is functional, but we need to address the visual conflicts with page content below.

GSAP Integration Process

1

Library Loading

Include GSAP core library and ScrollTrigger plugin before the closing body tag for optimal performance

2

Code Customization

Modify the provided parallax.js file to target your specific HTML selectors and container elements

3

Timeline Configuration

GSAP automatically handles the animation calculations based on scroll position and depth data attributes

Moving the Parallax Content Behind the Page Content

Professional parallax implementations require careful z-index management to ensure the effect enhances rather than interferes with page content. We'll move our parallax layers behind the main content using CSS stacking context.

  1. In main.css, add z-index positioning to the #hero * rule:

    #hero * {
       height: 100vh;
       width: 100%;
       position: fixed;
       z-index: -1;
       object-fit: cover;
    }
  2. Save and refresh to observe the change.

    • The page content now appears in front of the parallax layers, but transparency reveals the background animation.
    • Since our parallax elements use position: fixed, they're positioned relative to the viewport rather than their container, making overflow: hidden ineffective.

      We'll solve this by adding an opaque background to the main content area.

  3. Add a background color to the existing #content rule to mask the parallax layers:

    #content {
       background: var(—bg-color);

    Code Omitted To Save Space

    }

    NOTE: This implementation uses a CSS custom property (variable) already defined in the stylesheet. In production, you could use any solid color value such as #ffffff or rgb(255, 255, 255).

  4. Save your changes and test the complete parallax implementation.

    Scroll from top to bottom to experience the finished effect—smooth, performant parallax animation that integrates seamlessly with your page content!

Z-Index Stacking Context

Using z-index: -1 moves parallax elements behind page content, but requires setting background colors on overlaying content to prevent visual bleed-through.

Reducing the File Size of PNGs

Parallax implementations depend heavily on PNG files for transparency support, and at high resolutions, these files can reach enormous sizes that impact page performance and user experience.

Professional developers routinely use compression tools like TinyPNG.com, which can reduce PNG file sizes by 60-80% compared to Photoshop's default export settings, while maintaining visual quality. This optimization is crucial for mobile performance and SEO rankings in 2026, where Core Web Vitals significantly impact search placement.

PNG Optimization Impact

70%
average file size reduction
3+
image layers required minimum
Performance Optimization

Large PNG files can significantly impact page load times. Tools like tinypng.com can reduce file sizes by up to 70% without visible quality loss.

Making Sense of the Provided GSAP Code

If you're analyzing the GSAP implementation for deeper understanding or customization, here are the key concepts at work:

  • forEach provides elegant array iteration, replacing traditional for loops with more readable, functional programming syntax that's standard in modern JavaScript development.
  • offsetHeight is a native DOM API property (not GSAP-specific) that returns an element's total height including padding and borders—essential for accurate scroll calculations.
  • y: () => implements GSAP's function-based values, which recalculate automatically when ScrollTrigger refreshes (such as during window resizing). This ensures your parallax remains responsive across all device orientations and viewport changes, as explained by Jack Doyle in the original implementation notes.

Key JavaScript Concepts

forEach Loop Method

Modern JavaScript array iteration technique that provides cleaner syntax than traditional for loops. Processes each parallax layer individually.

offsetHeight Property

Native JavaScript property that returns element height including padding and borders. Essential for accurate scroll calculations.

Function-Based Values

GSAP's dynamic value system that recalculates animations on window resize events. Ensures responsive behavior across device changes.

Key Takeaways

1Parallax effects require minimum 3 layers moving at different speeds to create convincing depth perception
2PNG files with transparency are essential for layered parallax animations but require compression for optimal performance
3GSAP ScrollTrigger provides professional-grade scroll animation capabilities with minimal code implementation
4Fixed positioning with viewport units creates immersive full-screen parallax experiences across all devices
5Data attributes enable JavaScript communication for dynamic animation parameter control
6Z-index management is crucial for proper content layering and visual hierarchy in parallax designs
7Function-based GSAP values ensure animations remain responsive during window resize events
8Background color settings on page content prevent visual bleed-through from behind parallax layers

RELATED ARTICLES