GreenSock: Parallax Animation

Free JavaScript Tutorial

Dive into this comprehensive tutorial on creating a parallax scrolling animation using JavaScript, getting hands-on experience with topics such as setting up HTML, styling parallax layers, adding depth information, and leveraging GSAP.

This exercise is excerpted from Noble Desktop’s JavaScript for Front-End training materials and is compatible with JavaScript updates through 2023. To learn current skills in JavaScript with hands-on training, check out our Front-End Web Development Certificate, Full-Stack Web Development Certificate, and coding classes in-person and live online.

Topics covered in this JavaScript tutorial:

Setting Up the HTML, Styling the Parallax Layers, Adding the Depth Info, Using GSAP to Make the Parallax Work

Exercise Preview

preview parallax

Exercise Overview

In this exercise you’ll learn how to create a parallax scrolling animation.

JavaScript Development Certificate: Live & Hands-on, In NYC or Online, 0% Financing, 1-on-1 Mentoring, Free Retake, Job Prep. Named a Top Bootcamp by Forbes, Fortune, & Time Out. Noble Desktop. Learn More.

What is Parallax & How Does it Work?

Parallax is a visual effect where multiple layers move at different rates of speed to create a sense of three dimensional depth.

The key to making parallax convincing, is having 3 or more layers on top of each other, where far away objects move slower and as objects get closer to you, they move faster. It’s the different rates of speed which create the sense of depth.

One of the hardest parts of creating a parallax animation, is the Photoshop work. We’ve already done this for you, but you’ll need each image with the unwanted elements removed (transparent). To get them into your webpage with transparent backgrounds, you must save them as PNG. Below is how our 3 images (background.jpg, middleground.png, and foreground.png) look:

parallax layers

Getting Started

  1. For this exercise we’ll be working with the GSAP-Parallax folder located in Desktop > Class Files > JavaScript Class. Open that folder in your code editor if it allows you to (like Visual Studio Code does).
  2. In your code editor, open index.html from the GSAP-Parallax folder.
  3. Preview index.html in a browser.

    • Notice we’ve already added the full background image (which is not transparent), and a heading below that.
    • We’ll need to add the other transparent images over this image, and move the heading up on top of those layers.
  4. Leave the page open in the browser, so you can reload it later.

Setting Up the HTML

  1. Back in your code editor, find the hero div and we’ll see the background image and heading you just saw in the browser:

    <div id="hero">
       <img src="img/background.jpg">
       <h1>The Islands of Hawaii</h1>
    </div>
    
  2. Copy and paste the image code twice, and change their src so you have all 3 parallax images we’ll be layering on top of each other:

    <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 and reload the page in the browser.

    • From the top of the page, scroll down and notice you can see all the images one below the other.
    • We need to put them on top of each other in the same place (in a front to back layering) so they’ll initially look like a single image (users won’t know there are multiple layers).

Styling the Parallax Layers

  1. In your code editor, from the css folder open main.css
  2. Above the #content rule, add this new rule to make the #hero container fill the screen’s height:

    #hero {
       height: 100vh;
    }
    
  3. Below the #hero rule, add the following new rule to size and position any element inside the hero on top of each other (remember we have images and a heading):

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

    NOTE: * is a wildcard which targets any element. object-fit: cover; works like background-size: cover; but for regular images instead of background images.

  4. Save and reload the page in the browser.

    • Notice that you can’t scroll down to see what’s below the hero, but the images and heading remain fixed to the window with all layers stacking on top of each other. So at least their layering is now working.
    • Don’t worry that scrolling doesn’t work, the GSAP code we’ll add soon will animate them on scroll.
    • Notice the heading is at the top of the window. Let’s move it to the bottom.

Positioning the Heading at the Bottom

  1. Back in your code editor, below the #hero * rule, add the following:

    #hero h1 {
       display: flex;
       align-items: flex-end;
       justify-content: center;
       padding-bottom: 15vh;
    }
    
  2. Save and reload the page in the browser.

    • Notice the heading is now at the bottom of the window.
    • With the page styled properly, now we can add the scrolling animation.

Adding the Depth Info

The GSAP script we’ll be using requires us to tell it a depth for each layer, so elements that are farther back will move slower, and elements that are closer will move faster. For this we’ll use a data attribute in HTML. They are a way to add info (data) which you make up, that JavaScript can use.

  1. In index.html add the data-depth attributes shown below in bold:

    <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: data-depth is a made-up attribute we’re using to pass info to JS. For this script, 0 would be the farthest back and would not animate. The higher the number the faster it will move, therefore appearing closer to us. If you’re not happy with the speed of an element, you could tweak these numbers to your liking. You can also have as many layers as you want!

Using GSAP to Make the Parallax Work

  1. We need to link to the GSAP JavaScript file and the ScrollTrigger plugin. Add the following bold code before the closing </body> tag:

       <script src="js/gsap.min.js"></script>
       <script src="js/ScrollTrigger.min.js"></script>
    </body>
    
  2. Next we’ll link to a JS file with some GSAP code (which you’ll look at in a moment):

       <script src="js/gsap.min.js"></script>
       <script src="js/ScrollTrigger.min.js"></script>
       <script src="js/parallax.js"></script>
    </body>
    
  3. Save the file.
  4. From the js folder, open parallax.js

    This code was posted to the GSAP Forums tinyurl.com/gsap-parx by Jack Doyle, the creator of GSAP.

  5. All we have to do is point it at the correct IDs or classes we used our HTML. Change .header to #hero which points to our container.

    const tl = gsap.timeline({
       scrollTrigger: {
       trigger: "#hero",
    
  6. Change .header__background-layer to #hero * which points to the items inside the container (just like we did in the CSS).

    gsap.utils.toArray("#hero *").forEach(layer => {
    
  7. Save the file and close it.
  8. Reload the page in the browser.

    • Starting at the top of the page, watch the photo and heading as you scroll down.
    • The parallax effect should be working!
    • We have a problem though, we see the bottoms of the background images which aren’t moving as fast as the layers in front.
    • The parallax images are also covering the content lower in the page, so we have some fixing to do.

Moving the Parallax Content Behind the Page Content

First let’s move the content backwards so it’s behind the other page content. By default z-index is 0, so we have to make it less than 0 (in this case -1 will work) to move it backwards in the front to back ordering.

  1. In main.css add the following bold code to the #hero * rule:

    #hero * {
       height: 100vh;
       width: 100%;
       position: fixed;
       z-index: -1;
       object-fit: cover;
    }
    
  2. Save and reload the page in the browser.

    • Now the page content (the paragraph below the photo) is in front the parallax images, but we can see through the content to the photos behind it.
    • Setting overflow to hidden on the hero won’t work, because the elements inside are position fixed which makes them relative to the viewport (not their parent element).

      We’ll have to set a background color on the content to hide what’s behind.

  3. Back in your code editor, add the following bold code to the existing #content rule.

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

    Code Omitted To Save Space

    }
    

    NOTE: We’re using a color variable we’ve already defined for this page, but you could use a standard hex value here as well.

  4. Save and reload the page in the browser.

    Starting at the top of the page, scroll down and enjoy the finished parallax animation!

Reducing the File Size of PNGs

This technique relies on PNG files for their transparency. At such a large pixel width, their filesizes can be HUGE!

We highly recommend running PNG files through a compressor like tinypng.com which can reduce their filesize compared to what you’ll get out of most apps such as Photoshop.

Making Sense of the Provided GSAP Code

If you’re trying to make sense of the GSAP code provided, here are some things to note:

  • forEach is a way to loop over all array items. It’s like doing a for loop but with less code.
  • offsetHeight is JavaScript (not GSAP) which is a read-only property that returns the height of an element (including vertical padding and borders if there are any).
  • y: () => is a GSAP function-based value that does the calculations inside so whenever the ScrollTrigger refreshes (when the window is resized) and invalidates that timeline, it calls that function again and processes the new values accordingly (as stated by Jack Doyle who wrote this code).
photo of Dan Rodney

Dan Rodney

Dan Rodney has been a designer and web developer for over 20 years. He creates coursework for Noble Desktop and teaches classes. In his spare time Dan also writes scripts for InDesign (Make Book JacketProper Fraction Pro, and more). Dan teaches just about anything web, video, or print related: HTML, CSS, JavaScript, Figma, Adobe XD, After Effects, Premiere Pro, Photoshop, Illustrator, InDesign, and more.

More articles by Dan Rodney

How to Learn JavaScript

Master JavaScript with hands-on training. JavaScript is one of the world's most widely-used coding languages. Learn JavaScript and its libraries to start creating interactive websites and mobile apps.

Yelp Facebook LinkedIn YouTube Twitter Instagram