Simple Parallax with jQuery

September 4, 2010 in Code by

Shinyface Parallax

A quick demo of using jQuery for par­al­lax. This example just cre­ates a nice visual effect but it could eas­ily be con­ver­ted for more con­struct­ive pur­poses but I’ll leave that up to you.

Par­al­lax (for the sake of this post) is the effect whereby things at dif­fer­ent dis­tances move at dif­fer­ent rates, for example look­ing out of a train win­dow the closer items are the faster they move past you. This is as hor­ribly sim­pli­fied and inac­cur­ate descrip­tion but will suf­fice for the sake of this example.

I’ve used three trans­par­ent PNGs for this but you can use as many lay­ers as you like or eas­ily replace the PNGs with div tags con­tain­ing whatever con­tent you need.

View the demo.
View the javas­cript source.


This is very simple. The html you need is as follows:

  1. <div id=“Par­al­lax”>
  2.         <img src=“images/Bottom.png” />
  3.         <img src=“images/Middle.png” />
  4.         <img src=“images/Top.png” />
  5. </div>

See, told you it was simple. The div is the outer con­tainer into which the lay­ers belong. Add the images in order of the bot­tom one (smal­lest) first. Job done.

The Images (or layers)

The images (or lay­ers) you use should each be a dif­fer­ent size, the big­ger the image the more move­ment. Each image must be at least as big as the viewer, if you set one side of it to be the same size as the viewer and another to be lar­ger it will only move on that axis, which is a nice effect in itself. So if your image is the same height as the viewer but wider it will only move horizontally.

This may be stat­ing the obvi­ous, but I’ve used trans­par­ent pngs, you must be able to see the lower images through the upper ones. To cre­ate them I used a pho­toshop file with a group for each image. This meant I could check how they would look before I out­put them. You can view the three images here:


You can view the entire CSS file here. The import­ant parts are as follows.

  1. #Par­al­lax {
  2.         background-color: #880088;
  3.         height: 500px;
  4.         over­flow: hid­den;
  5.         pos­i­tion: rel­at­ive;
  6.         width: 750px;
  7. }

The back­ground color can be whatever you fancy. Bear in mind that if all your lay­ers are trans­par­en­cies the back­ground color will show through. Of course you could make the bot­tom layer fully colored, pat­terned or whatever you fancy. You could also give the #Par­al­lax div a back­ground image if you wanted.

The width and height are import­ant, remem­ber your images should all the same dimen­sions or big­ger than this div. Over­flow must be set to hid­den to ensure that tags within this div will not cause it to change it’s size and will not poke out of the sides.

The rel­at­ive pos­i­tion is required as we will be set­ting the tags within the div to abso­lute and we want them to be posi­tioned rel­at­ively to this div, not to the document.

  1. #Par­al­lax img {
  2.         pos­i­tion: abso­lute;
  3.         top: 0;
  4.         left: 0;
  5. }

Each of the images within the div (or whatever you use for lay­ers) must be set to use abso­lute pos­i­tion­ing so that we can move them around with jQuery. I’ve set their ini­tial pos­i­tions to the top left corner but you can set them to wherever suits.

The Javas­cript

This uses jQuery for the heavy lift­ing. It could be con­ver­ted into a handy little jQuery plu­gin but I wanted to keep it as simple as pos­sible for the sake of the example, plus oth­ers have already done that.

  1. jQuery(doc­u­ment).ready(func­tion($){
  2.         $(’#Par­al­lax’).mouse­move(
  3.                 func­tion(e){
  4.                 /* Work out mouse position */
  5.                 var off­set = $(this).off­set();
  6.                 var xPos = e.pageX - off­set.left;
  7.                 var yPos = e.pageY - off­;
  9.                 /* Get per­cent­age positions */
  10.                 var mou­s­eX­Per­cent = Math.round(xPos / $(this).width() * 100);
  11.                 var mou­seY­Per­cent = Math.round(yPos / $(this).height() * 100);
  13.                 /* Pos­i­tion Each Layer */
  14.                 $(this).chil­dren(‘img’).each(
  15.                         func­tion(){
  16.                                 var diffX = $(’#Par­al­lax’).width() - $(this).width();
  17.                                 var diffY = $(’#Par­al­lax’).height() - $(this).height();
  19.                                 var myX = diffX * (mou­s­eX­Per­cent / 100);
  20.                                 var myY = diffY * (mou­seY­Per­cent / 100);
  21.                                 var cssObj = {
  22.                                         ‘left’: myX + ‘px’,
  23.                                         ‘top’: myY + ‘px’
  24.                                 }
  25.                                 $(this).anim­ate({left: myX, top: myY},{dur­a­tion: 50, queue: false, eas­ing: ‘lin­ear’});
  27.                         }
  28.                 );
  30.                 }
  31.         );
  32. });

What this does is whenever the mouse is moved over the viewer (#Par­al­lax div) it cal­cu­lates it’s pos­i­tion over the div (as per­cent­ages) then moves each of the inner images by that same per­cent of their overflow.

Firstly work out the xPos and yPos. To do this we sub­tract the view­ers x and y off­set from the x and y mouse pos­i­tion. This is because the mouse pos­i­tions returned are rel­at­ive to the doc­u­ment not to the viewer. The off­set val­ues give us the view­ers pos­i­tion rel­at­ive to the document.

Next, work out the hori­zontal and ver­tical pos­i­tion of the mouse pointer as a per­cent­age (0 = the top of the viewer, 100 = the bottom).

Loop through each image, for each one work out the dif­fer­ence in width and height between the image and the viewer. The image’s new pos­i­tion for each axis is the per­cent­age cal­cu­lated earlier for that axis of the dif­fer­ence for that axis. So if the mouse is dead cen­ter on the viewer the hori­zontal pos­i­tion is 50% of the dif­fer­ence between the image width and the viewer width.

Finally, we cre­ate an object con­tain­ing the new CSS set­tings and apply it via a very short anim­a­tion which gives the effect a nice smooth fin­ish. You can just jump to the new pos­i­tion but it looks a little too rough for my tastes.


comments powered by Disqus