Parallax scrolling - Hoe werkt het?

Geplaatst op 29/05/2011 in JavaScript

Steeds vaker kom je websites tegen waarbij bepaalde elementen op de pagina langzamer of sneller meebewegen tijdens het scrollen. Ook de nieuwe website van 45north heeft het op de homepagina. Maar wat is dit precies en hoe krijg je het voor elkaar?


Deze techniek heet ‘parallax scrolling’. Laten we eerst even aan Wikipedia vragen wat parallax nou precies betekent.

Parallax is het verschijnsel dat de schijnbare positie van een voorwerp ten opzichte van een ander voorwerp en/of de achtergrond varieert als men het vanuit verschillende posities bekijkt. Dit verschijnsel is des te sterker naarmate het voorwerp zich ten opzichte van de achtergrond dichter bij de waarnemer bevindt: Dingen die dichterbij liggen, lijken door de verandering van kijkrichting veel meer mee te verschuiven dan dingen die verder weg liggen.

Simpel gezegd: objecten die ver weg zijn bewegen langzamer dan objecten die dichtbij zijn. Stel je zit in de trein en ziet in de verte een enorme berg. Deze berg lijkt heel langzaam te bewegen, terwijl objecten die dichterbij zijn (bomen, huizen, etc.) sneller bewegen. Hoe verder het object is, des te langzamer deze meebeweegt. Hier een klein voorbeeld van Wikipedia:

Parallax

Parallax Scrolling

Dit parallax effect wordt vaak gebruikt in games, maar kom je tegenwoordig ook steeds vaker tegen op websites. Dit heet parallax scrolling en houdt in dat bepaalde elementen op de pagina op een andere snelheid meebewegen terwijl je scrollt. Het geeft een gevoel van diepte bij je website en kan, mits goed uitgevoerd, er erg tof uitzien.

Vroeger zou je Flash moeten gebruiken om dit goed voor elkaar te krijgen, maar tegenwoordig is JavaScript ook een goede optie. Dit heb ik ook bij de website van 45north gedaan en het werkt perfect. De gebruiker moet echter wel een redelijk snelle browser hebben om dit goed te laten werken. Je kan het laten werken in IE6, maar verwacht er dan niet veel van. Ook niet onbelangrijk: het gaat niet werken op de iPhone of iPad. Daar wordt het scrollen helaas anders geregeld.

CSS3 Multiple Backgrounds

Er zijn verschillende manieren om parallax scrolling op een website voor elkaar te krijgen. Je kunt meerdere <div> tags met een achtergrond op je pagina zetten en deze met JavaScript laten meebewegen. Je kunt hetzelfde doen met allemaal <img> tags. Er is echter een veel betere optie: CSS3 multiple backgrounds. Hiermee kun je verschillende achtergronden toevoegen aan één tag. Je hebt dus niet allerlei verschillende HTML tags nodig om bewegende elementen toe te voegen aan je pagina.

Maar hoe werkt dit dan? Het is vrij simpel:

background-image: url(images/flower.png), url(images/cloud.png);

Je geeft een extra achtergrond mee door een komma te plaatsen. Je kunt hetzelfde doen om deze achtergronden een positie te geven:

background-position: 20px 300px, 50px 600px;

Nu heb je beide achtergronden gepositioneerd. Je kunt met CSS3 alle background-* eigenschappen een CSV meegeven. Geen lelijke <div> tags meer om een extra achtergrond toe te voegen.

Belangrijk bij parallax scrolling is dat je de background-attachment op fixed zet. Als je dit niet doet zal het allemaal een stuk trager zijn en ook een beetje schokkend bewegen bij het scrollen.

De HTML en CSS

Nu je de basis principes van de CSS begrijpt en weet wat parallax scrolling is kunnen we doorgaan met het maken van de HTML en CSS van ons voorbeeld. Eerst de HTML:

<div id="backgrounds"></div>

We maken een <div> met als id ‘backgrounds’ aan. Je kunt de achtergronden ook op de <body> tag stoppen, maar ik vond het handiger om dit te scheiden. Zometeen waarom. Deze <div> willen we over de gehele breedte en hoogte van de pagina hebben. Ook zullen er twee achtergronden aan worden toegevoegd.

#backgrounds {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background: url(../images/flower.png), url(../images/cloud.png);
  background-attachment: fixed; /* Beide achtergronden zijn nu fixed */
  background-position: 50px 600px, 20px 200px;
  background-repeat: repeat-y, repeat-x;
}

Als we nu kijken zien we de twee achtergronden op de pagina staan. De bloemetjes worden over de y-as herhaald en de wolken over de x-as. Stop nu een hoop tekst in de <body>, zodat er een scrollbar verschijnt. Als je nu scrollt zie je dat de achtergronden gewoon blijven staan. Nu moeten we ervoor zorgen dat deze gaan meebewegen met het scrollen. Dit doen we met JavaScript.

De JavaScript

Ik zal hier jQuery gaan gebruiken om het scrollen te registreren en de achtergronden te laten bewegen. Het opvangen van de scroll-event is vrij simpel:

$(function(){
  $(window).scroll(function(){
    // Doe wat
  });
});

Nu kunnen we JavaScript gaan uitvoeren als de gebruiker aan het scrollen is. De informatie die we nodig hebben van de gebruiker is hoe ver hij/zij heeft gescrolld. Dit doen we als volgt:

$(function(){
  $(window).scroll(function(){
    var top = $(this).scrollTop();
  });
});

In top wordt nu steeds een cijfer gestopt. Dit is de hoeveelheid pixels die de gebruiker naar beneden heeft gescrolld en wordt gemeten vanaf de bovenkant van de browser. We kunnen nu op basis hiervan bepalen wat de nieuwe y-positie wordt van de elementen en de background-position aanpassen.

$(function(){
  $(window).scroll(function(){
    var top = $(this).scrollTop();
    var flowers = 600 - top;
    var clouds = 200 - top;
    $("#backgrounds").css({ backgroundPosition: "50px " + flowers + "px, 20px " + clouds + "px" });
  });
});

Nu zullen de bloemen en de wolken meebewegen met het scrollen. Ervoor zorgen dat de elementen langzamer meescrollen is vrij simpel.

var flowers = 600 - (top * 0.4);
var clouds = 200 - (top * 0.2);

Je vermenigvuldigt de top waarde met een getal onder de 1. Wil je juist dat de elementen sneller bewegen dan het scrollen, dan vermenigvuldig je het met een getal boven de 1. Als je echter niks doet met de top waarde zal alles gewoon meescrollen.

En dat is gelijk hoe je parallax scrolling voor elkaar krijgt. Je stopt een hoop elementen op de pagina en laat deze bewegen op basis van hoe ver je bent gescrolld. Het is nu alleen een kwestie van meerdere elementen toevoegen, deze op de juiste plek zetten en mee laten bewegen.

Oudere Browsers

We hebben gebruikgemaakt van de CSS3 multiple backgrounds om allerlei elementen toe te voegen aan onze pagina. Deze manier heeft echter een nadeel: oudere browsers (waaronder IE6/7/8) ondersteunen dit niet. Hoe kunnen we checken of de browser multiple backgrounds ondersteunt? Hiervoor is iets genaamd Modernizr. Hiermee kun je erg gemakkelijk checken of de browser jouw CSS3 ondersteunt. Aangezien we hier alleen multiple backgrounds gebruiken kunnen we een functie uit deze plugin halen:

function multipleBgTest(){
  var el_style = document.createElement("div").style;
  el_style.cssText = 'background:url(//:),url(//:),red url(//:)';

  // If the UA supports multiple backgrounds, there should be three occurrences
  // of the string "url(" in the return value for el_style.background
  return new RegExp("(url\\s*\\(.*?){3}").test(el_style.background);
}
var multipleBg = multipleBgTest();

Nu komt er in de multipleBg variabele true of false. De waarde is true als de browser meerdere achtergronden ondersteunt en false als dit niet het geval is. Dan kunnen we nu een simpele check hierop gaan doen.

$(function(){
  if(multipleBg) {
    $(window).scroll(function(){
      var top = $(this).scrollTop();
      var flowers = 600 - (top * 0.4);
      var clouds = 200 - (top * 0.2);
      $("#backgrounds").css({ backgroundPosition: "50px " + flowers + "px, 20px " + clouds + "px" });
    });
  } else {
    // JS voor oudere browsers.
  }
});

Dan komt nu het punt waarom ik een <div> met als id ‘backgrounds’ heb aangemaakt. Hier kunnen we nu namelijk allemaal losse <div> tags ingooien. De achtergronden zijn dan gegroepeerd in een backgrounds <div> in plaats van los in de <body> tag.

$("#backgrounds").append('<div id="flowers_nocss3"></div><div id="clouds_nocss3"></div>');

Nu moet er alleen nog voor worden gezorgd dat ook hier de achtergronden in worden gestopt. Ik heb bij de 45north website een aparte stylesheet hiervoor gemaakt. Deze laad ik via JavaScript in:

if(document.createStyleSheet) {
  document.createStyleSheet("stylesheets/no-css3.css");
} else {
  $("head").append('<link rel="stylesheet" href="stylesheets/no-css3.css" type="text/css" />');
}

Hier zouden we dan het volgende in kunnen doen:

#backgrounds {
    background: none;
}
#flowers_nocss3 {
    position: fixed; 
    left: 0; top: 0;
    width: 100%; height: 100%;
    background-image: url("../images/flower.png");
    background-position: 50px 600px;
    background-attachment: fixed;
    background-repeat: repeat-y;
}
#clouds_nocss3 {
    position: fixed; 
    left: 0; top: 0;
    width: 100%; height: 100%;
    background-image: url("../images/cloud.png");
    background-position: 20px 200px;
    background-attachment: fixed;
    background-repeat: repeat-x;
}

Dan kunnen we nu beide elementen laten bewegen op basis van het scrollen.

$(window).scroll(function(){
    var top = $(this).scrollTop();
    var flowers = 600 - (top * 0.4);
    var clouds = 200 - (top * 0.2);
    $("#flowers_nocss3").css({ backgroundPosition: "50px " + flowers + "px" });
    $("#clouds_nocss3").css({ backgroundPosition: "20px " + clouds + "px" });
});

De kans is echter groot dat dit nogal traag gaat in oudere browsers als je veel elementen toevoegt. Je kunt er ook voor kiezen om het parallax effect voor deze browsers gewoon uit te zetten. Zorg er dan voor dat alles position: absolute krijgt en dat de achtergronden background-attachment: scroll meekrijgen. Dit is vooral handig om te doen voor de iPhone en iPad, aangezien de browsers hierop parallax scrolling niet ondersteunen. Aangezien de iPhone en iPad wel meerdere achtergronden ondersteunen moet je een andere check doen. Hier een voorbeeld:

var userAgent = window.navigator.userAgent;
var isMobileSafari = false;
if(userAgent.match(/iPad/i) || userAgent.match(/iPhone/i) || userAgent.match(/iPod/i)) {
    isMobileSafari = true;
}

Dan kun je daar weer een if-statement op doen en op basis daarvan alles positioneren.

Aan de slag!

Zoals je hebt gezien is parallax scrolling niet zo heel lastig om voor elkaar te krijgen. Waar het meeste werk in gaat zitten is alles ook op andere browsers laten werken. Om jullie op weg te helpen heb ik op Github een simpel voorbeeld geplaatst hoe je parallax scrolling voor elkaar krijgt. Doe er je voordeel mee.

Dat was dan mijn tutorial over parallax scrolling. Ik hoop dat je er wat aan hebt gehad en lekker verder kunt gaan met het maken van een mooie website. Laat ook even in de reacties hieronder zien wat je hebt gemaakt. Dat vind ik altijd leuk om te zien. :)

Comments (3)

Geplaatst op 31/05/2011 om 22:41

Wat zeker ook de moeite waard is om te bekijken is deze verzameling parallax scrolling websites. Zitten echt geniale sites tussen, zoals ‘Ben the Bodyguard’ en ‘Nike Better World’.

Thomas Gerards
Thomas Gerards

Geplaatst op 22/01/2012 om 14:10

Ten eerste: Goed uitgelegt!

Ik probeer het toe te passen voor een studie project, maar er is 1 ding waar ik niet uit kom. Ik wil het graag horizontaal werkend krijgen. Ik heb al van alles geprobeerd, maar vrees dat het in het javascript zit. Ik hoop dat je me op weg kan helpen…

Geplaatst op 23/01/2012 om 08:16

Ik kan je er wel bij helpen. Wat is het probleem precies?

Place a new comment

To place a comment, please log in via:
Het is snel en gemakkelijk. Kies een website waarmee je wilt inloggen en je kunt meteen reageren. Geen gedoe met wachtwoorden en een speciaal account bij ons.
Deze website maakt veelvuldig gebruik van JavaScript. U heeft dit uitstaan.