Creating a basic parallax scrolling effect using CSS and JavaScript

Updated: July 24th, 16

The most dominate trend of 2015 in web design undoubtedly is the parallax
scrolling effect, with no signs that's waning. Parallax
scrolling transforms the page into a fun slideshow where different elements
on the page move at different speeds relative to the scrolling of the
page. In this tutorial we'll familiarize ourselves with how a basic
parallax scrolling page is created in CSS and JavaScript, and gain insight
into the whole shebang in the process.

The anatomy of a parallax scrolling effect

"a special
scrolling technique in computer graphics, wherein background images move by
the camera slower than foreground images, creating an illusion of depth in a 2D
video game and adding to the immersion."

As it pertains to a webpage, a parallax effect is tied to the scrolling
of the page; as this action is performed, different elements on the page
such as the background image and foreground elements move/ animate at a
different pace relative to the scrollbar's, all orchestrated using
JavaScript. Take a look at the following simple parallax scrolling example,
which consists of a large background image plus 3 layers moving at different
speeds relative to the scrollbar:

The background-size: cover CSS3 property ensures that
the image covers the entire area of the element; it makes for light work of
plastering every inch of our BODY with the background image, though this
property is resource intensive, and should be used with restraint in
parallax scrolling applications.

Then comes our two bubbles. Each one is rendered as a background image of
a DIV that's fixed on the page and positioned at the top left corner of the
page:

Lets break down what's going on here. Ignoring the
requestAnimationFrame() method for now, first, we reference the two
bubble layers by their IDs. Inside the parallaxbubbles() function, we move
each bubble by a fraction of the current vertical scroll
amount, thus causing the bubbles to move at a different speed relative to
the scrolling. The negative operator added in front of the scrolltop
variable causes each bubble to move in the opposite direction of the scroll.

Continuing on, we tap into the "scroll" event of the window object to
execute code whenever the window gets scrolled. But instead of just calling
parallaxbubbles() directly inside this event, we'll take a more roundabout
route that favours performance over succinctness. And that route involves
calling parallaxbubbles() indirectly, inside JavaScript's requestAnimationFrame() method. The later is a JavaScript method (with
various prefixed versions depending on the browser) that accepts a function reference
and executes that function on the next available screen repaint. In
other words, it stutters the execution of the function if necessary until
the browser is able to render a new frame on the screen, preventing needless
calling of the target function that only degrades performance. Whenever
we're associating code to window's scroll event, we can expect that code to
be invoked in rapid succession- optimizing performance then is key, and
wrapping any animation code inside
requestAnimationFrame() is an important step to doing that.

A parallaxing fish that moves horizontally across the screen

So we now have a page with two parallaxing bubbles, each moving at
reduced rates compared to the scrolling. There's no logic that dictates
where the bubbles should be precisely on the page relative to how much the
document has been scrolled.

For the next object we'll be parallaxing, lets arrange it so that the
object glides from the left edge of the window to the right in sync with the
scrollbar. When the scrollbar is at the very top, the object is at the left
edge, gradually moving until the scrollbar is at the very end, when the
object will be at the right edge. The fish object as it is will be
positioned similarity to the other layers, but near the left and bottom of
the window.

We add a DIV with the ID "fish" to the page first (view demo page source
code), then reference it using the "fish" variable in our JavaScript. What
follows are two variables that get the total height of the document and the
height of the browser window at the moment, respectively:

Inside the parallaxbubbles() function, we can calculate exactly how much
of the scrollbar has been scrolled as a percentage of the entire scrollable
track (where 0 means scrollbar is at the very top, 100% means at the very
bottom) with this magic line:

The sub operation (scrollheight-windowheight), or
subtracting the height of the window from the total height of the document,
nets us the total distance the scrollbar is able to travel before it reaches
the bottom of the document. It is as this point that we want our fish
object to be at the right edge of the window.

When we divide scrolltop (how much the scrollbar has currently traveled)
with (scrollheight-windowheight), we get, as a percentage of the total
distance, how much the scrollbar has traveled. Multiplying that by 100
converts that information into a percentage value, where 0 means the
scrollbar is at the very top, and 100 at the very end of the scrolltrack:

Now that we know how much the scrollbar has scrolled in percentage, we
can directly feed that value as part of the fish layer's left property,
moving it proportionally to how much the scrollbar has scrolled:

The -100 value is added so the initial left position of the
fish is
-100%, hiding it from view. As the user scrolls the page, that value
gradually increases until it reaches 0%. That's when the fish appears at
the right edge of the window (the actual fish image appears as a background
positioned to the
very right inside the fish layer).

Next we'll address the big elephant in the room- parallax scrolling and
mobile devices.