How to solve element flicker while scrolling with parallax effect in JavaScript?

Marakoss picture Marakoss · Jan 25, 2012 · Viewed 15.4k times · Source

I am trying to re-create website with parallax effect using JavaScript. That means that I have two or more layers, that are moving different speeds while scrolling.

In my case I'm moving only one layer, the other one remains static: layer 1 = website text; layer 2 = element background;

for this I'm using simple source code (with jQuery 1.6.4):

var docwindow = $(window);

function newpos(pos, adjust, ratio){
   return ((pos - adjust) * ratio)  + "px";
}

function move(){
   var pos = docwindow.scrollTop();
   element.css({'top' : newpos(pos, 0, 0.5)});
}

$(window).scroll(function(){
   move();
});

The Problem: - All calculations are done right and the effect "works" as expected. But there is some performance glitch under some browsers (Chrome MAC/Windows, Opera MAC, IE, paradoxically not Safari).

What do I see during scrolling? - While scrolling the background moves in one direction together with scroll, but it seems to occasionally jump few pixels back and then forth, which creates very disturbing effect (not fluid).

Solutions that I tried: - adding a timer to limit scroll events - using .animate() method with short duration instead of .css() method.

I've also observed, that the animation is smooth when using .scrollTo method (scrollTo jQuery plugin). So I suspect that there is something wrong with firing scroll events (too fast).

Have you observed the same behavior? Do you know, how to fix it? Can you post a better solution?

Thanks for all responses

EDIT #1: Here you can find jsfiddle demonstration (with timer): http://jsfiddle.net/4h9Ye/1/

Answer

Bruno Silva picture Bruno Silva · Jan 25, 2012

I think you should be using scrollTop() instead and change the background position to fixed. The problem is that setting it to absolute will make it move by default when you scroll up or down.

The flicker occurs because the position is updated as part of the default browser scroll and updated again as part of your script. This will render both positions instead of just the one you want. With fixed, the background will never move unless you tell it so.

I've created a demo for you at http://jsfiddle.net/4h9Ye/2/ .