WK10: Scroll-based Interaction and Animation

Scroll-based interactions are a simple way for your users to trigger animations and events to enhance their experience. Although they are simple for the user, the difficulty to achieve them with code can range from extremely simple to extremely intricate.

This tutorial is focussed on understanding the underpinnings of interacting with scroll on the web, and a couple of Javascript and jQuery plugins that help with more complicated scroll interactions.

To get started with creating scroll-based interactions with your own code, you’ll need to listen out for when your user scrolls. In jQuery, we target the window object and add an event listener that runs a function every time the window is scrolled. It looks like this:

$(window).scroll(function() {
    console.log("You're scrolling!");
});

Try that code in your own project, refresh, open your console and start scrolling. You’ll see that the console logs out that string a lot! Once you’ve got a function running, it’s then all about what you want to achieve with your scroll interactions. You have to start playing the role of the detective, snooping around for different object properties such as scroll positions, element positions, distances and heights, doing some calculations and then applying your own new styles and effects as necessary.

The first piece of information you’ll need when working with scroll animations is to know where the user’s scroll position is (the distance from the top of their window to the top of the page). You can find this out by calling .scrollTop() on the window object like so.

$(window).scroll(function() {
    var scrollPositionTop = $(window).scrollTop();
    console.log(scrollPositionTop);
});

Once you have this, you’ll want to compare this number to the position of your elements. Finding how far an element is from the top of the document and comparing the numbers gives you an indication of how close the element is to the top of the screen. If you also work out where the bottom of the screen is in comparison to the document and the bottom of the element to the screen you can then determine whether the element is within the viewport. All the variables needed to ascertain whether or not an element is within the viewport are listed below.

$(window).scroll(function() {
    // Window Information
    var windowHeight        = $(window).outerHeight();
    var scrollTopPosition   = $(window).scrollTop();
    var scrollBotPosition   = scrollTopPosition + windowHeight;

    // Element Information
    var element             = $('.target-element');
    var elementHeight       = element.outerHeight();
    var elementOffset       = element.offset();
    var elementTopPosition  = elementOffset.top;
    var elementBotPosition  = elementTopPosition + elementHeight;
});

By doing the work yourself you’re able to have the most control over how your effects work. However, if you’re simply trying to add a class when an element is in view, then yes, there’s a library for that.

scrollClass.js

scrollClass.js is a simple library for doing this. It has an extremely lightweight footprint (because it’s an extremely simple effect) but as you should already know, adding a class to an element can give you a lot of power in way of animation.

Check out this demo of the types on effects you can create by taking advantage of new classes:

To use it start by installing their js file after your installation of jQuery. Then simply take the elements you want to have a new class added when they are in the viewport and add a class so that they are targetable by jQuery, and a data-scroll-class attribute defining the class you want to be added to the element.

<div class="example" data-scroll-class="awesome-animation"></div>

Then, initialise the plugin on your elements like so:

$('.example').scrollClass();

Once you’ve completed those steps, any element that has the class ‘example’ will have their individual data-scroll-class values added to their class list once the element is scrolled into the viewport.

scrollClass.js Documentation

Skrollr.js

Parallax animation is the illusion of depth that is achieved by animating visual elements on different depth planes at a different speed.

Disney pioneered the technique in traditional cel-animation with the invention of their multi-plane camera:

The technique of driving parallax animation on web pages using the scroll position has become popular in recent years.

The technique requires Javascript, because we need to respond to user input (scrolling) in order to drive the animation.

Though there’s nothing stopping you from scripting your own parallax effect from scratch, there are many JavaScript libraries that can help you achieve the effect with minimal additional coding.

The skrollr library is a vanilla Javascript library perfect for creating parallax effects.  While not the simplest library, it is certainly one of the most flexible, and likely powers many of the more advanced parallax scrolling sites you have seen.  As always, take a look at a few options before you decide which library (if any) is best suited to your needs.

skrollr.js Documentation skrollr.js Homepage

Note that skrollr is not just for parallax animation.  It is a general purpose scroll-driven animation library.  You can animate pretty much anything with it. Take a look at the examples to see what else it can do.

To get started with skrollr, download and install their Javascript file, then initialise the plugin like so (you very likely will want to disable the forceHeight option, as it can create unwanted space at the bottom of your document).

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/skrollr/0.6.30/skrollr.min.js"></script>
var s = skrollr.init({
  forceHeight: false
});

This might look a little different to some of the other plugins; there’s no jQuery involved! This plugin is purely Javascript, not that it should bother you. Once it’s installed you’ll need to follow their documentation to create what are essentially keyframes for your elements. This is done by adding data attributes to your elements that define a comparison point between your element and the viewport.

Sound confusing? It is a little at first. Do read the documentation thoroughly, but focus on the part that describes relative mode.

Instead of defining key frames relative to the document (i.e. absolute), we are able to define them depending on the position of any element in relation to the viewport.

The syntax is data-[offset]-(viewport-anchor)-[element-anchor], where offset can again be any integer and defaults to 0. Both viewport-anchor (mandatory) and element-anchor (optional) can be one of top, center or bottom. If element-anchor is omitted, the value of viewport-anchor will be taken (just like with background-position). Here are some examples of key frames and their meaning.

Take a look at this codepen to see it in action.

See the Pen Skrollr by Michael (@michaelschmidt_) on CodePen.0

Now try it out yourself, with a more interesting example.

Parallax clouds with skrollr

The result might look something like the below example:

fullPage.js

Fullpage.js is basically one huge fullscreen carousel flipped on the side and controlled with scroll. Its a nifty plugin if you’ve got clean-cut sections of information and can give you a point of difference over your standard scrolling page. It does, however, come with some challenges, such as fitting your panel information on your screen for smaller devices and scroll threshold bugginess.

To get started with fullPage.js, check out their webpage and documentation on Github.

fullPage.js Documentation fullPage.js Homepage

To get started, follow their documentation on Github and install their CSS stylesheet and jQuery plugin. You can use a CDN for this plugin also like so:

<body>
    <!-- fullPage Stylesheet -->
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/fullPage.js/2.9.4/jquery.fullpage.min.css" />
    <!-- Your Stylesheet -->
    <link rel="stylesheet" type="text/css" href="css/style.css" />



    <!-- jQuery -->
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <!-- fullPage.js -->
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fullPage.js/2.9.4/jquery.fullpage.min.js"></script>
    <!-- Your Script -->
    <script type="text/javascript" src="js/script.js"></script>
</body>

Once you’ve installed their CSS and Javascript code, you need to follow their markup instructions for your HTML. Use the exact classes as they’ve defined if you don’t want to go about customising it with your own class names.

<div id="fullpage">
	<div class="section">Some section</div>
	<div class="section">Some section</div>
    <div class="section">
        <div class="slide"> Slide 1 </div>
        <div class="slide"> Slide 2 </div>
        <div class="slide"> Slide 3 </div>
        <div class="slide"> Slide 4 </div>
    </div>
	<div class="section">Some section</div>
</div>

Then initialise fullPage in your Javascript file:

$('#fullpage').fullpage();

See the Pen Basic fullPage.js by Michael (@michaelschmidt_) on CodePen.0

As with most plugins, fullPage.js can be customised with an options object so check out what options you might need.

$('#fullpage').fullpage({
    navigation: true
});

fullPage.js also implements a whole range of state-based classes (just like slick.js does) that allow you to create custom transitions and animations. For example, when you are viewing a section it is given the class ‘active’. This allows you to transition elements in and off screen quite easily. Check out this demo that quickly demonstrates how to take advantage of this:

See the Pen Adding Animations Using fullPagejs Active Class by Michael (@michaelschmidt_) on CodePen.0

And one of their own demo’s shows how you can make some neat little effects.

Sometimes you might face the issue that you only want your animation playing one, and not to be cancelled and reset when the active class is removed from the section when the user moves to the next slide. In this case what you need is a class to be added and for it to remain despite leaving the section.

To do this you have to take advantage of ‘callbacks’ or ‘events’ that plugins often write that allow you to listen to particular changes or interactions that occur with the plugin. Both slick.js and fullPage.js have available events to create callback functions.

In fullPage.js, one such event callback you can define is the afterLoad event. Here you can define a function to run every time a new section is loaded or switched into view. The documentation defines some information that the plugin will pass to your function so you can make some logic based changes. For the afterLoad callback, you have access to the anchorLink if its provided, and the index (in this case 1-based, not 0-based) of the section.

What does that look like in your code? Something like this perhaps, where the index is used to identify the current section and add a ‘visited’ class to the section. This way we can have a class added to the section that won’t leave when the user leaves.

$('#fullpage').fullpage({
    afterLoad: function(anchorLink, index){
        var currentSectionIndex = index - 1;
        var sections = $('#fullpage').children();
        var currentSection = sections.eq(currentSectionIndex);
        currentSection.addClass('visited');
    },  
});

See the Pen fullPage.js Visited Callback by Michael (@michaelschmidt_) on CodePen.0

If fullPage.js is your thing, you can find an in-depth tutorial by tuts+ for customising your fullPage.js install here:

fullPage.js tutorial by Tuts+