Pixel Acres

Build a parallax scrolling website interface with jQuery and CSS

Parallax scrolling website interfaces have been popping up all over the place recently. I didn’t want to miss out on the fun, so I have put together a parallax scrolling demo built using jQuery and CSS.

Parallax scrolling interface

Parallax what?

Even if you’re not familiar with the term “parallax scrolling” you will certainly be familiar with the technique. Parallax scrolling is a 2d animation process that creates an illusion of depth by animating foreground layers faster than background layers. When you observe the landscape from a moving car, objects closer to the car appear to pass you faster than scenery further away. Parallax scrolling uses the same principle to trick the viewer into thinking they are observing a 3d scene.

Demo and Download

My demo web page shows one approach to building a vertical parallax scrolling interface:

View demo
Download source

You can scroll in the usual fashion, use the navigation menu at the right-hand side of the page, or the next/prev buttons that appear underneath each article. As you scroll, the page’s four content layers are animated independently of one another to create an illusion of depth.

The scrolling looks smoothest in Safari (at least that’s the case on my PC), but my demo should work in any modern browser.

Disclaimer 1: Because this is just an experiment I’ve not spent any time optimising the demo to work on mobile devices. I wanted to keep the demo lean ‘n’ mean, and not clutter it by sniffing mobile browsers and forking my code. On a production site you’d want to ensure that the site degrades gracefully on mobile devices, where scroll events and fixed positioning might work in unexpected ways.

Disclaimer 2: The navigation menu in my demo is inspired by the menu on the Nike Better World website. If you plan on implementing a similar menu on a production site, please be aware of its origin.

How it works

The articles and background layers are given a fixed positioned with CSS, and assigned a z-index so that the foreground layers appear above the background layers. The four layers are: small clouds, large clouds, balloon/landscape images, articles.

/* foreground (ballons/landscape) */
#parallax-bg3 {
    z-index: 3;
    position: fixed;
    left: 50%; /* align left edge with center of viewport */
    top: 0;
    width: 940px;
    margin-left: -470px; /* move left by half element's width */

Within each layer individual content elements are absolutely positioned. This was the most fiddly part of the process, since the elements need to positioned in such a way that they align in a pleasing manner when the user scrolls to any of the four articles. In this case it was really just a process of trial and error.

#bg3-1 {
    position: absolute;
    top: -111px;
    left: 355px;
#bg3-2 {
    position: absolute;
    top: 812px;
    left: 321px;
/* etc... */

A few lines of jQuery control the parallax effect, triggered by a scroll event. I was surprised how easy this was to achieve, it is literally just a handful of lines of code.

function parallaxScroll(){
    var scrolled = $(window).scrollTop();

As you can see the CSS top property is used to move each layer as the user scrolls. The foreground layer is always aligned to the top of the document, while the movement of other layers is adjusted according to their depth. The lower a layer sits in the stack, the less distance it is moved.

The rest of the jQuery is concerned with controlling the navigation menus. When the user clicks a navigation button the page scrolls to the top of the associated article. In the event that the user has JavaScript disabled, regular HTML anchor links still allow the page to be navigated, but without any fancy pants animations.

Next steps

I’m sure there are plenty of other approaches to parallax scrolling, and hopefully my experiment provides a starting point for your own explorations of the technique.


I have updated the demo so that each parallax layer is given a fixed, rather than absolute, position. This approach gives a smoother scrolling effect.

158 Responses to “Build a parallax scrolling website interface with jQuery and CSS”

  1. Vivi says:

    Hi Jonathan,

    Thanks for this wonderful tutorial!

    There’s one part that I’m a little confused about…I can’t seem to get my dot navigation to set as an active state after adding two new sections. I was wondering if you can take a look at my coding and see what I’m doing wrong here?

    function redrawDotNav(){
    var section1Top = 0;
    // The top of each section is offset by half the distance to the previous section.
    var section2Top = $(‘#introduction’).offset().top – (($(‘#featuredwork’).offset().top – $(‘#introduction’).offset().top) / 2);
    var section3Top = $(‘#featuredwork’).offset().top – (($(‘#featuredproducts’).offset().top – $(‘#featuredwork’).offset().top) / 2);
    var section4Top = $(‘#featuredproducts’).offset().top – (($(‘#recententries’).offset().top – $(‘#featuredproducts’).offset().top) / 2);
    var section5Top = $(‘#recententries’).offset().top – (($(‘#contactinfo’).offset().top – $(‘#recententries’).offset().top) / 2);
    var section6Top = $(‘#contactinfo’).offset().top – (($(document).height() – $(‘#contactinfo’).offset().top) / 2);;
    $(‘nav#bullets a’).removeClass(‘active’);
    if($(document).scrollTop() >= section1Top && $(document).scrollTop() = section2Top && $(document).scrollTop() = section3Top && $(document).scrollTop() = section4Top && $(document).scrollTop() = section5Top && $(document).scrollTop() = section6Top){
    $(‘nav#bullets a.contactinfo’).addClass(‘active’);

    Any help is appreciated! Thanks!

  2. Anton says:

    This a very useful tutorial, thanks a lot for posting it. Unfortunately it does not work on iphones and ipads thou

  3. Colin says:

    Hey this is really clean awesome piece. Thanks alot

  4. diego says:

    Hey man, thanks!
    Finally one tutorial easy to understand about parallax scrolling effect.

    One question:

    How you can disable the mouse scroll action, so that navigation is done only with the buttons?

  5. Dennis Flojo says:

    This is neat!

  6. Dennis says:

    Great tutorial! Would be great to see this in touch swipe event horizontally.

  7. amo says:

    why is swapping images for new different ones complicated?

Leave a Reply