0%

# Motion Parallax: A Primer[ Benjamin Paine | Jan 09, 2017 | Resources ]

### What is Motion Parallax?

Motion Parallax is the name given to the phenomenon of objects closer to you seeming to move faster than objects farther away. If you've ever driven down a country road, you've probably noticed the scenery in the background seeming to move much slower than the power poles next to the road.

### How can we implement it?

While it would be costly, and perhaps difficult, to implement a full 3D engine in CSS/JS (excluding the unreliable transform), we can fake it rather simply. An initial thought would be to manipulate the background-position property of an image, and that would work, but for reasons we'll soon find out, it's not ideal. One of the first things we need to do is decide the range of motion of the image desired, and the range of motion of the screen. If, for instance, we want our image to move 200 pixels over the height of the screen, each step of motion must be 200/$(window).height() pixels, starting from the moment the <div> is visible, or when $(window).scrollTop+$(window).height()==$(div).offset().top. See the results of this idea below.

HTML
CSS
JS
Result
0<div class="parallax_test">
1     Test!
2</div>

0.parallax_test{
1     background:url("../_img/iss.jpg");
2     background-size:400px 400px;
3     display:block;
4     width:600px;
5     height:400px;
6     background-repeat:no-repeat;
7}

0$(document).ready(function(){ 1$(window).scroll(function(){
2          $(".parallax_test").css("background-position","0px "+(($(window).scrollTop()-$(window).height())/($(window).height()/200))+"px");
3     }
4}

Test!

### What's wrong with that?

First and foremost, hard-coding anything will only lead to headaches down the road, and our above solution won't work for images much farther down a page. If you're on mobile, you may even see some of the <div> not covered by the image.

On top of that, we have the problem of different sized background images. Ours fits roughly into a 600x400 space, because it has close to a 3:2 ratio. Other images might not be so lucky. We also run into the problem of using absolute pixel sizes at all — if we want to use percentages, or cover or contain for our background image, we're out of luck.

The solution that we use has two separate <div>'s within the main <div>. This allows us to manipulate the "background" <div> in a straightforward way, while having content in a "content" <div>. See the full solution below.

HTML
CSS
JS
Result
0<div class="parallax" id="parallax_demo">
1     <div class="content">Test!</div>
2     <div class="background"></div>
3</div>

0.parallax{
1     display:block;
2     height:200px;
3     width:100%;
4     overflow:hidden;
5     position:relative;
6}
7.parallax .content{
8     position:absolute;
9     width:100%;
10     height:100%;
11     display:block;
12     font-size:2em;
13     z-index:1;
14}
15.parallax .background{
16     display:block;
17     width:100%;
18     height:400%;
19     position:absolute;
20     background-repeat:no-repeat;
21     top:0px;
22     left:0px;
23}
24.parallax#parallax_demo .background{
25     background:url("../_img/para_1.jpg");
26     background-size:contain;
27     z-index:0;
28}

0$(window).scroll(function(){ 1$(".parallax").each(function(){
2                    if(isVisible(this)){
3                         var px = parseInt($(window).scrollTop() -$(this).offset().top);
4                         \$(this).find(".background").css({"top":(px/2)+"px"});
5               }
6          });
7     });

Test!