Parallax effects can be an extremely effective way to engage users during the simple act of scrolling. What is normally a simple process of moving static content along the screen can become an act of moving through a makeshift, HTML world. While the effect can certainly be abused, when applied with a light, elegant touch, it can breathe new life into your site.
Unfortunately this effect is hampered on touch devices, where tactile feedback and intertial scrolling would perfectly suit parallax animation. Mobile browsers place a limit on script execution during scroll, so your carefully crafted parallax effects won’t happen until scrolling has come to a complete halt. As you can imagine, this is far from impressive.
As a personal goal to not only make parallax effects as simple as possible, but to make them work on mobile browsers where these effects are notoriously difficult, I created a scrolling parallax library called Stellar.js.
If you’re feeling impatient, you can skip straight to the demo. At this point, you might be wondering what the issue with mobile browsers happens to be, and how Stellar.js lets us overcome this.
The overflow problem
When we got our first taste of HTML5-capable mobile browsers, one of the first things web designers and developers noticed was their lack of scrolling overflow support.
On desktop we took it for granted that we could add a scroll bar to any element. This ability was taken away from us on these new platforms which, inside their own native applications, commonly made use of small, nested scrolling panes in order to better fit more content on such relatively tiny screens.
Plenty of people noticed this shortcoming, and some library authors weren’t ready to be defeated.
Enter touch scrolling libraries
It didn’t take long for some smart developers to find ways around this limitation by creating libraries which emulate native scroll using CSS3 transforms.
While their need is somewhat dimished with the overflow-scrolling property, they still prove vital for overcoming our JavaScript issues. By emulating native scroll, the browser no longer throttles our script execution.
There’s quite a few to choose from, and all of these will integrate with Stellar.js:
- iScroll by Matteo Spinelli
- Zynga Scroller from Zynga
- Scrollability by Joe Hewitt
Before we use one of these libraries, we first need to create a standard, non-mobile parallax example.
Marking up a simple desktop-only demo
To get started, we need a basic HTML page with jQuery, Stellar.js and some parallax elements:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
A couple of files are referenced here which haven’t been created yet: “script.js” and “style.css”.
Scripting and styling
The code in script.js initialises Stellar.js, which activates all elements with data-stellar-ratio data attributes:
1 2 3 4 5 6 |
|
In style.css we specify how the content should look, paying particular attention to the styling of our “pixel” elements:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
|
We now have a very basic, desktop-only parallax demo but, as you’d expect, we are going to make this work cross-platform.
Adding mobile support
We first need to make some adjustments to the markup. We need to add a mobile-friendly meta tag:
1
|
|
We next need to add a couple of divs for iScroll, namely a “wrapper” div and a “scroller” div:
1 2 3 4 5 6 7 |
|
Finally, we need to include the JavaScript for iScroll:
1
|
|
The complete HTML file now looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Detecting mobile devices
Now that we have iScroll available, and the required markup, we need to update our script.js file.
We’re going to be introducing some local variables that we don’t want leaking into the global scope, so our first step is to wrap our code in an immediately invoked function expression (IIFE):
1 2 3 |
|
In order to activate iScroll only when we’re on a mobile WebKit browser, we need to do some dreaded user agent sniffing:
1 2 |
|
In order to style the mobile version differently, we can now use our isMobileWebkit flag to add a class to our HTML element:
1 2 3 |
|
Finally, we need to initalise iScroll if we’re on mobile:
1 2 3 4 |
|
Now we can initalise Stellar.js differently whether we’re on desktop or mobile.
Understanding Stellar.js on mobile
Before we continue, it’s important to try to understand how Stellar.js is able to work with a touch scrolling library like iScroll.
Stellar.js has the concept of scroll properties which are adapters that tell it how to read the scroll position. The default scroll property is, appropriately enough, “scroll”, which covers the standard onscroll style animation.
When using Stellar.js’ default settings, it’s equivalent to writing this code:
1 2 3 |
|
Here you can see that we’ve specified that “window” is the source of our scrolling, and we read its scroll position using the “scroll” scroll property adapter.
Once we use iScroll, there is no longer a scroll position in the traditional sense. Native scroll is being simulated by moving the “scroller” div inside the “wrapper” div using CSS3 transforms.
Thankfully, Stellar.js has a “transform” adapter to cover this exact case. All we have to do is point Stellar.js at the div being moved, and specify which “scrollProperty” to use:
1 2 3 |
|
Performant positioning in Mobile WebKit
Repositioning elements rapidly is fairly demanding on mobile devices. In order to achieve a seamless effect, we need to ensure that our parallax effects are hardware accelerated.
In WebKit, hardware acceleration is triggered by using “translate3d”. Stellar.js provides support for this method of positioning via the “transform” position property adapter:
1 2 3 4 |
|
By using this adapter, our parallax effects should now be as smooth as possible.
Hooking Stellar.js up to iScroll
Now that we’ve seen all the individual pieces needed to make our JavaScript work, it’s time to see the final script.js in its entirety:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Of course, this won’t work until we’ve updated our style sheet.
Styling for mobile
Finally, we add our mobile-specific styles which act on the body tag and our new iScroll containers:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Seeing the end result
If you take a look at the final page, you’ll see we now have a page with scrolling parallax which works on desktop and mobile.
From here we have a base to play with our parallax site, while ensuring it works correctly cross-platform. At this point, if you haven’t already, it’s a good idea to read through the Stellar.js documentation to get a better idea of the control you have over the effect.
Have you made a cross-platform parallax site with Stellar.js? Let me know on Twitter, or post a link in the comments.
Update (27 Jan 2013): This article now reflects changes made in Stellar.js v0.6