Parallax scrolling websites have become very popular recently. Some of the effects are pretty striking and create a very engaging user experience. I’ve been looking into parallax scrolling for something I’m designing but noticed a real issue with speed when using the effect in Firefox, so over the weekend, I set about addressing the problem. Here’s what I came up with:
What causes the issue?
The techniques used to achieve the parallax effect essentially boil down to hooking into the document’s scroll
event and adjusting element properties based on the position of the vertical scroll bar. If you’re a Firefox user (especially if you’re on a PC) you’ve probably noticed that these sites appear to lag or jump around while you scroll. Generally speaking, these sites lack the slick, responsive experience you get from Safari, Chrome, Opera or IE.
The reason Firefox struggles to render parallax scrolling websites at a reasonable speed is because it doesn’t dispatch scroll
events anywhere near as frequently as the other browsers. This means the script responsible for modifying element properties doesn’t execute as often and this ruins the parallax effect.
Increasing the scroll event frequency
The idea is to make the scrolling more responsive without changing the way events are added to the document and avoiding the need for helper functions with code paths for different browsers. All I want to do is increase the rate at which Firefox dispatches scroll
events.
Increasing the scroll event frequency requires creating and dispatching a custom DOM scroll
event. Creating the event is easy, the big problem is; how to dispatch the event while the user is scrolling the page?
The solution lies in a Firefox specific “feature”. Firefox triggers mouse events inside scroll bar tracks. Exploiting this feature allows us to detect mouse movement in the document’s vertical scroll bar using the mousemove
event. Since mousemove
fires every time the mouse moves, it can be used to dispatch a custom scroll
event to the document
giving us the increased frequency required to achieve a fluid parallax effect.
The second step is to sync the mouse-wheel scroll repaints. To do this I’ve added a handler to the Gecko specific DOMMouseScroll
event. The handler disables the default scrolling action and dispatches the custom scroll
event. Since the default action is disabled, I also have to recreate the scrolling effect by modifying the document.documentElement.scrollTop
property based on the event data.
The script
Here it is:
Try it out
Visit the Nike Better World and Iutopi websites (any parallax site will do) in Firefox and scroll through them (noting the lag), then paste the JavaScript above into the console (Firebug) and execute it. Scroll again, things should look much smoother — especially if you’re using a PC.