0

I use this code for a parallax effect for a website I'm creating, works great in safari and firefox(mac). But in chrome(mac) it gets laggy, the same for when I try it on iPad and on my iPhone 6.

Javascript:

  var ypos,image;
  function parallax() {
    image = document.getElementById('bgImage');
    ypos = window.pageYOffset;
    image.style.top = ypos * .4+ 'px';
}
window.addEventListener('scroll', parallax),false;

html:

    <img class="img-responsive" id="bgImage" src="images/bgtopg.jpg">
</div>
     <div id="box1" class="content">
            <h1>Heading</h1>
            <p>Lorem ipsum dolor sit amet.....</p>      
        </div>

(img-responsive - from bootstrap)

css:

#bgImage {
    position: relative;
    z-index: -1
  }

Any ideas what is causing the lag-effect?

tommyj
  • 3
  • 2
  • try to use CSS transforms to set position of the elements instead, – LJ Wadowski Jun 01 '15 at 15:29
  • Once you're done reading my answer, you should watch this to get an easy understanding of how the javascript event stack works. YOUTUBE: https://www.youtube.com/watch?v=8aGhZQkoFbQ – Joseph Casey Jun 01 '15 at 15:56

2 Answers2

1

What's happening

'Laggy' behavior with javascript events is a common problem. Essentially what you're running into is overloading your event stack. It's piling up so high that it creates a choppy effect.

Your Options

The solution to this is two fold. Either you can choose the path of hardware acceleration or debouncing. Debouncing should be your first solution, and hardware acceleration should be used when you've confirmed that you're not simply overloading your script.

Debounce that shiz!

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
document.addEventListener("DOMContentLoaded", function(event) { 
function debounce(func, wait, immediate) {
 var timeout;
 return function() {
  var context = this, args = arguments;
  var later = function() {
   timeout = null;
   if (!immediate) func.apply(context, args);
  };
  var callNow = immediate && !timeout;
  clearTimeout(timeout);
  timeout = setTimeout(later, wait);
  if (callNow) func.apply(context, args);
 };
};

var myEfficientFn = debounce(function() {
 console.log("HEY STOP MOVING ME AROUND!");
}, 25);

window.addEventListener("mousemove", myEfficientFn),false;
});
Move your mouse around a whole lot and look at your console.

We have the technology to accelerate!

https://stackoverflow.com/a/15203880/1596825

Community
  • 1
  • 1
Joseph Casey
  • 1,225
  • 1
  • 12
  • 33
0

You could try doing the parallax animation effect with translateY instead of manipulating the top style of the image. This is an excellent post by Paul Irish that describes why you should be doing translation instead of top/left/right/bottom.

So instead of:

image.style.top = ypos * .4+ 'px';

You could do:

image.style.webkitTransform = 'translateY(' + ypos * .4 + 'px)';
image.style.transform = 'translateY(' + ypos * .4 + 'px)';

Good luck, let me know if it helps!

jollelj
  • 940
  • 1
  • 8
  • 18