-
Notifications
You must be signed in to change notification settings - Fork 500
Home
jQuery Parallax Recreating the Nike Better World Parallax Effect Tutorial New Page Edit Page Page History A couple of months ago, I created a jQuery Vertical Parallax Demo that manipulated CSS to make multiple backgrounds move at different speeds relative to the users movement of the scroll bar. This type of effect is slowly appearing across various websites on the web, achieved using many different techniques. Nikebetterworld took the idea to a new level.
In today's tutorial, we're going to take the original jQuery Parallax script I wrote and recreate a webpage similar to Nikebetterworld.
If you'd like to see what we'll be creating, go check out the demo or download the files.
Our page will consist of 6 sections: header, footer and 4 articles. On the right, we'll place an unordered list that links between the articles and remains fixed on the page so it doesn't move.
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script> <script type="text/javascript" src="scripts/nbw-parallax.js"></script> <script type="text/javascript" src="scripts/jquery.localscroll-1.2.7-min.js"></script> <script type="text/javascript" src="scripts/jquery.scrollTo-1.4.2-min.js"></script> <script type="text/javascript" src="scripts/jquery.inview.js"></script> <script type="text/javascript"> $(document).ready(function(){ $('#nav').localScroll(); }) </script>To start, at the top of the page, we'll reference all of the JavaScript files we'll use to make the effect work. The scripts we're using are:
- jQuery 1.4.4
- The script I wrote (which we'll cover shortly)
- jQuery localscroll (which smoothly scrolls between articles)
- jQuery scrollTo (also needed for smooth scrolling)
- jQuery Inview (determines whether a particular article is in view)
I won't cover what all of the CSS does, just that which is relevant to the working of the effect. Let's take a look at the CSS for the HTML container I just mentioned above:
#intro{ background:url(images/firstBG.jpg) 50% 0 no-repeat fixed; color: white; height: 600px; margin: 0; padding: 160px 0 0 0; } The first article (#intro), will have one background image and a height of 600px. The width isn't defined so it will stretch to 100% of the window. Each background image used for the articles I have made 1900px so the majority of monitors will have a full image background. Anything over 1900px will see a white border.
.story{ margin: 0 auto; min-width: 980px; width: 980px; } Inside of the #intro container, we have .story which is present in every article container. This purely keeps each article centered in the browser and with a width of 980px, almost every monitor will see the website without the need for horizontal scroll bars.
Some of the articles have multiple backgrounds. Nikebetterworld achieved this using extra HTML in the article container which is exactly what I've done for the "Multiple Backgrounds" article, just like this:
#second .bg{ background: url(images/trainers.png) 50% 0 no-repeat fixed; ... position: absolute; ... z-index: 200; } This div is also given an absolute position and a high z-index to make sure it appears above everything else.
However, although this is the best way to achieve support across all browsers for multiple backgrounds, it's also possible to use CSS3 multiple backgrounds, which I demonstrate in the fourth article in the demo "Empty Containers vs CSS3 Multiple Backgrounds".
Using CSS3 means we don't have to place empty containers in the markup and leave the styling to CSS which is how things should (and one day will) be. So, let's look at the CSS for the fourth article container:
#fourth{ background: url(images/bubbles2.png), url(images/bubbles2.png), url(images/bubbles1.png), url(images/fourthBG.jpg); background-position: 50% 0, 50% 0, 50% 0, 50% 0; background-color: #036; background-attachment: fixed; background-repeat: repeat, repeat, repeat ,no-repeat; } As you can see, I've used CSS3 to give one element multiple backgrounds. I've also given each of those backgrounds their own position values. We'll be manipulating these values in jQuery shortly.
Note: In my original jQuery Parallax Demo, I used shorthand CSS to define all of the backgrounds values which is what I did in this demo to begin with too. However, because I used shorthand, when I started manipulating the background positions via jQuery, it meant not only were the background positions being changed, but so too were the background urls and this made the jQuery very heavy. Infact, only Chrome is able to cope with running that original script smoothly at this time, but I do plan to take what I've learnt in this demo and optimize the code in the hope it will run smoothly across all browsers too.
So, it is entirely up to you which method you use to create multiple backgrounds. Extra markup means the effect will work across all browsers but if you're just trying this demo for fun, I recommend CSS3 because you can achieve much more with it.
Now we get to the meat of this tutorial! First thing's first, optimization! As mentioned above, my original jQuery Parallax Demo was quite a difficult script for browsers to deal with because it was asking them to do a lot. This script is much lighter thanks to the above mentioned CSS along with a good amount of jQuery optimization:
var
We will need the height of the browser window on a few occasions so we'll put that into a variable too:
var windowHeight = $window.height(); Next up, comes our 'inview' event which uses thejQuery Element in view Event Plugin:
Next, we have three functions which will be called at three separate occasions. Firstly, the positioning of the unordered list I mentioned, that is fixed to the right of the window:
function RepositionNav(){
var windowHeight =
Our second function is where the magic happens. It's the little bit of code that works out how to move each background image respective to the position of the scrollbar:
function newPos(x, windowHeight, pos, adjuster, inertia){ return x + "% " + (-((windowHeight + pos) - adjuster) * inertia) + "px"; }
When we call the function further in the script, we'll provide it five different arguments, which are much like settings that make each call to that function unique. They are as follows:
x = the horizontal position of the image windowHeight = the height of the window pos = The position of the scrollbar adjuster = A value that moves the background image into a position we want inertia = The speed at which the background image moves in relation to the scrollbar The function then uses these arguments we've fed it to return one property that changes the CSS property, 'background-position' of whichever article we request. An example output would be:
50% -400px That value is yet to be applied though. That's where our final function comes in.
function Move(){ var pos = $window.scrollTop(); ... } Move() is to be called whenever the user moves the scrollbar window or resizes the browser. It starts by working out the position of the scrollbar.
Then, we have several "if statements" that check to see if an article is "in view":
if($firstBG.hasClass("inview")){ $firstBG.css({'backgroundPosition': newPos(50, windowHeight, pos, 900, 0.3)}); } In this "if statement", we check to see if the first article has the class of "inview". Remember, our "in view" check earlier on applied this class for us. If the article is "in view", we change the CSS property, 'backgroundPosition' using the newPos function as explained above.
The function continues to test if each article has the class of "inview" and if so, it changes the "backgroundPosition" property.
You will notice in this demo, the second article has two lines of code that each change a different "backgroundPosition". One is for the full background of the second article, the other changes the background of the extra bit of markup:
As I mentioned, in the fourth article I used CSS3 multiple backgrounds so when the function tests the fourth article to see if it has the class of "inview" and it does, the following code is used:$fourthBG.css({'backgroundPosition': newPos(0, windowHeight, pos, 200, 0.9) + ", " + newPos(50, windowHeight, pos, 0, 0.7) + ", " + newPos(50, windowHeight, pos, 0, 0.5) + ", " + newPos(50, windowHeight, pos, 700, 0.3)}); The newPos function is simply called multiple times to work out the position of each background image.
One final piece of code for this function:
$('#pixels').html(pos); At the bottom of the Nikebetterworld website, they show you how many pixels you've scrolled to reach the bottom of the page. I included this in the demo and the code above replicates that.
Whew, that's it right? Almost!
Up to now, all of that code hasn't actually done anything. We've simply set up lots of code to be activated when we need it. We just need a few events now to allow us to utilise all of those functions.
Immediately after the last function, I've called the function 'RepositionNav()'. This is triggered immediately after the script loads to make sure the unordered list of links is vertically positioned in the window.
Next up is a window resize event:
$window.resize(function(){ Move(); RepositionNav(); }); When a user resizes the browser, we call the Move() and RepositionNav() functions. These both make sure that the demo works well regardless of the window size.
$window.bind('scroll', function(){ Move(); }); And finally, the scroll event. When a user scrolls, call the Move() function to move the background images relative to the position of the scrollbar.
Having seen the Nikebetterworld website I was blown away but a little disappointed too. I didn't get the chance to put my jQuery Parallax Demo into good use -- it just existed as a demo. Having tried to replicate the Nikebetterworld website though, I have a lot of respect for whomever it was that developed it. Not only did they create a truly awesome effect, they made the website cross browser compatible too. They also used other cutting edge technologies such as HTML5 and font replacement to make a truly amazing experience.
Parallax effects are slowly being used across more and more sites. Having made this demo and learnt a lot along the way, I still have a lot of ideas for making the demo code better but also for taking the script in new directions and achieving even more amazing effects with it. Keep your eye on my blog for more techniques, or if you beat me to it, give me a shout because I'd love to see what you've made.

