Get codin’

Preparations

What you will need:

Let’s start with the HTML structure. We will create a parent container and give it an id of ‘hero’. Then we want to add multiple divs with class “layer” ( one for each layer you have created) and data-type attribute with value “parallax.”

#hero

.layer{“data-type” => “parallax”}

.layer{“data-type” => “parallax”}

.layer{“data-type” => “parallax”}

.layer{“data-type” => “parallax”}

.layer{“data-type” => “parallax”}

Let’s add our basic styling. We’ll start by styling the id “hero”. I have set the height of the illustration to 800 px.

#hero {

height: 800px;

overflow: hidden;

position: relative;

}

Now, let’s move to styling the repeating class of layers. All of them will have the same height as the id “hero” container base positioning, and we’ll add position: fixed.

.layer {

background-position: bottom center;

background-size: auto;

background-repeat: no-repeat;

width: 100%;

height: 800px;

position: fixed;

z-index: -1;

}

The next thing we’ll want to do is add the layer images we have previously prepared. We’ll create another set of classes, one for every layer. Then, place the URL of the picture inside the “background-image” property.

Let’s not forget to update the HTML file and assign the classes to the proper divs in our order, with the first layer being the background; the subsequent layers will be stacked on top of each other as you add the next numbers.

#hero

.layer.layer-01{“data-type” => “parallax”}

.layer.layer-02{“data-type” => “parallax”}

.layer.layer-03{“data-type” => “parallax”}

.layer.layer-04{“data-type” => “parallax”}

.layer.layer-05{“data-type” => “parallax”}

Javascript time

Now, let’s add a method that will check if the user has begun scrolling down.

window.addEventListener ‘scroll’, (event)

The EventTarget.addEventListener() method registers the specified listener on the EventTarget it’s called on. The event target may be an Element in a document, the Document itself, a Window, or any other object that supports events (such as XMLHttpRequest).

Then let’s store the value of pixels that the document has already been scrolled vertically into the topDistance variable. To do that, we’ll use the pageYOffset property.

window.addEventListener ‘scroll’, (event) ->

topDistance = @pageYOffset

After that, we want to select all the layers in our illustration and store them into a variable called ‘layers’. To do that, we’ll use the querySelectorAll method and data attribute inside the HTML that we have specified previously.

window.addEventListener ‘scroll’, (event) ->

topDistance = @pageYOffset

layers = document.querySelectorAll("[data-type='parallax']")

Next thing we’ll have to do is to loop through all the layers and apply proper transform to each of the layers. But before that, we need to specify one more thing inside of our HTML file, the data-depth. It will allow us to control how fast the elements move, let’s not dig too deep into the values inside of it yet, we’ll get back to this later on.

#hero

.layer.layer-01{“data-type” => “parallax”, "data-depth" => "0.10"}

.layer.layer-02{“data-type” => “parallax”, "data-depth" => "0.20"}

.layer.layer-03{“data-type” => “parallax”, "data-depth" => "0.50"}

.layer.layer-04{“data-type” => “parallax”, "data-depth" => "0.80"}

.layer.layer-05{“data-type” => “parallax”, "data-depth" => "1.00"}

For looping through all the elements, we’ll use the for loop. We start the loop by creating a variable where we will be storing our layers (coffescript allows us to do that all with a simple sentence for layer in layers); then take the value from the data-depth attribute we specified inside of our HTML. After that, we calculate the movement of the layers by multiplying the distance from the top of the page by our data-depth for the given layer. Element with the value of 1.0 will flow normally with the rest of the document, you can think of this as a “parallax off” state.

The last thing we do is we update the final value of movement to the layer’s CSS parameter of transform translate3d, to do that we’ll use style property along with all the prefixes for transform.

To make things more readable and DRY, we’ll store the translate3d property in a variable called ‘translate3d’.

for layer in layers

depth = layer.getAttribute(‘data-depth’)

movement = -(topDistance * depth)

translate3d = 'translate3d(0, ' + movement + 'px, 0)'

layer.style['-webkit-transform'] = translate3d

layer.style['-moz-transform'] = translate3d

layer.style['-ms-transform'] = translate3d

layer.style['-o-transform'] = translate3d

layer.style.transform = translate3d

Now when we specify the data-depth=”1.00" the element will move with the page as a standard element with no parallax effect. All values that are less than 100 will have the parallax effect.

Mobile

For mobile we’ll be turning off the parallax version and replacing it with static image to save up on performance and file size (since it requires multiple png files). To do that we’ll create a new div below id hero with id of hero-mobile and apply display: none along with the background and height property.

To show it instead of parallax we’ll use simple media query and apply display: none to desktop version, while overriding our display: none with display: block on hero-mobile.

Further tweaking involves adding background-position to the individual layer classes to position elements as you wish.