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
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.
Here it is:
Try it out