build wordpress website in 5 days build motocms website in 5 days

Webpage Scrolling Animation Effects with CSS3 & jQuery

A bit of website animation can be fun and enticing to new visitors. Modern web design has opened doors to allow greater effects to be accomplished with fewer lines of code. Animated page elements do not offer major alterations on content, but can provide a more extraordinary user experience.

In this tutorial I want to demonstrate how to build UI elements which animate into view as the user scrolls down the page.The animation transitions will be accomplished using CSS3 while scrolling is detected using jQuery. This combination allows a more even split of code, and one day we might even be able to port this over to a pure CSS effect. Take a peek at my live demo to see the finished product.

Live Demo - Download Source Code

Getting Started

I've included a local copy of the jQuery library along with a CSS stylesheet. All of the animations will be written into CSS using class names, while jQuery will handle the scroll trigger.

Inside the body section I've wrapped all the content into a #wrapper div which is centered on the page. Since only specific elements will be animated we can wrap those into separate div sections using more unique classes.

1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
  <div id="wrapper">
    <h1>Animated Scroll Effects</h1>
 
    <p class="desc">Continue scrolling down to see the magic.</p>
 
    <p class="desc">Animated blocks use CSS classes to setup direction and flow of each item.</p>
 
    <br><br><br><br>
 
    <div class="animateblock centerleft">
      <img src="img/macbook-laptop.png" alt="macbook icon"><!-- https://www.iconfinder.com/icons/289610/computer_device_laptop_mac_mac_os_macbook_netbook_notebook_workplace_icon -->
    </div>

This block of code includes the very first animated div which displays a small MacBook icon. Each animated section will use the class .animateblock. This doesn't have to be a div element, but it helps to apply the animation onto a container rather than a single paragraph or img tag.

Also the second class name will affect how the object animates into view. By default .animateblock will just fade the opacity up from 0% to 100%. But using margins and other properties we can easily rearrange elements to work into the page from a specific direction. For example this first block uses .centerleft which centers the icon while animating in from the right side over to the left. Other animated divs follow a similar setup with <br> tags adding extra space for scrolling room.

Let's delve into the stylesheet to see how these animated classes work.

CSS Design & Animation

The page itself has a number of typical resets based off the Eric Meyers reset code snippet. I'm also using a dark tiled background to provide more contrast on the page. Naturally these effects can work with any style and should not be limited to one type of page structure or color scheme.

1
2
3
4
5
6
7
8
9
10
11
12
13
/* animated elements */
.animateblock {
  padding: 8px 0;
  color: #fff;
  opacity: 0;
  -webkit-transition: all 0.55s linear;
  -moz-transition: all 0.55s linear;
  transition: all 0.55s linear;
}
 
.animateblock.animated {
  opacity: 1;
}

.animateblock is the absolute bare necessary class to get any HTML object animating into view. jQuery will target each element using this class and check when it should be animated. To actually make the animation happen we use an additional class .animated.

Take note how the original animate block uses the CSS3 transition property, along with some related browser prefixes. This will transition every unique property once the .animated class is added onto the element - meaning you could even create your own additional classes for new animation effects.

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/* animation transition styles */
.animateblock.left {
  margin-left: -2%;
}
.animateblock.left.animated {
  margin-left: 12%;
}
 
.animateblock.right {
  display: block;
  margin-left: 100%;
}
.animateblock.right.animated {
  margin-left: 70%;
}
 
.animateblock.top {
  display: block;
  width: auto;
  text-align: center;
  margin-top: -25px;
}
.animateblock.top.animated {
  margin-top: 0px;
}
 
.animateblock.btm {
  display: block;
  width: auto;
  text-align: center;
  margin-top: 25px;
}
.animateblock.btm.animated {
  margin-top: 0;
}
 
.animateblock.centerleft {
  display: block;
  width: auto;
  text-align: center;
  margin-right: -10%;
}
.animateblock.centerleft.animated {
  margin-right: 0;
}
 
.animateblock.centerright {
  display: block;
  width: auto;
  text-align: center;
  margin-left: -10%;
}
.animateblock.centerright.animated {
  margin-left: 0;
}
 
.animateblock.center {
  margin-left: 2%;
}
.animateblock.center.animated {
  margin-left: 42%;
}
 
.animateblock.size {
  display: block;
  width: 10%;
  text-align: center;
}
.animateblock.size.animated {
  width: 100%;
  height: 100%;
}
.animateblock.size img {
  max-width: 100%;
  height: auto;
}

Each class is broken up into a section of the primary class(like .left) along with the final animated class(like .left.animated). Only one of these classes should be added onto the animated div to get the additional effects. You can animate in from the top or bottom, left or right, even moving into the center by resizing the div as it comes into view. Not all CSS properties support transition effects so you'll have to try out ideas to see what works best.

Scroll Trigger with jQuery

The last bit of code to get this script working can be found at the bottom of my HTML file. jQuery needs access to some crucial information, most notably a list of each .animateblock element to cycle through. Each animation will trigger once a user has scrolled to the point where an element is 3/4 of the way down the window. It's not too confusing but let's break into each piece of logic.

1
2
3
4
5
6
7
8
$(function(){
  var $elems = $('.animateblock');
  var winheight = $(window).height();
  var fullheight = $(document).height();
 
  $(window).scroll(function(){
    animate_elems();
  });

First I'm setting up a few global variables. $elems is a jQuery object containing all the matched elements queued for animation. winheight pulls the browser window's height and fullheight pulls the entire webpage's height, both values in pixels.

Next I'm running a new function on the jQuery .scroll() event handler. Each time a user scrolls we're calling a separate function named animate_elems(). This is where all the logic happens and where it's determined at what point to apply the .animated class onto each element.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  function animate_elems() {
    wintop = $(window).scrollTop(); // calculate distance from top of window
 
    // loop through each item to check when it animates
    $elems.each(function(){
      $elm = $(this);
 
      if($elm.hasClass('animated')) { return true; } // if already animated skip to the next item
 
      topcoords = $elm.offset().top; // element's distance from top of page in pixels
 
      if(wintop > (topcoords - (winheight*.75))) {
        // animate when top of the window is 3/4 above the element
        $elm.addClass('animated');
      }
    });
  } // end animate_elems()
});

Inside here we pull a new value for wintop each time the user scrolls. This will hold a total pixel value offset from the very top of the page. This value is useful to check out the visitor's distance from the next animated page element.

$elems.each() uses the jQuery .each() loop to run through the targeted element. Before crunching any numbers we first check each element's class to see if it's already using .animated. If so then we return true which will move right along to the next item. Once every element has been animated the function won't need to perform any more calculations.

But if the currently-targeted element has not animated then we need to see if it should animate. topcoords is a variable containing the offset pixel value of the specific element's position from the top of the page. Each animated div will have a different px coordinate, so it's important we loop through each one separately.

The final bit of logic may seem confusing but it makes plenty of sense once you understand how it works. Here's how the if{} logic is written: wintop > (topcoords - (winheight*.75))

wintop checks the pixel value of the user's current scrolled position. If it's greater than topcoords then we'd know the targeted div is right at the top of the screen - this is a little too late to be animating something. Instead we need a smaller number which equals just about 75% of the page height. So to get this value I've taken the window's height multiplied by .75, and this number is subtracted from the element's position.

Now the logic will check for when the user's scroll position is just around the element's position at the lower 25% of the page. The visitor's position will still be at the "top", but subtracting 75% of the window height creates this new boundary. You might even try changing that .75 value to something like .6 or .8 just to see how this affects each animation.

Closing

There are some nice alternative plugins you could try out which build animation effects solely in jQuery. Many of these plugins are much larger but they offer more dynamic effects which are supported in a wider array of browsers. Yet CSS3 is growing more popular with each passing month and it's certainly not phasing out anytime soon. Feel free to download a copy of my source code and try building your own animated effects into future web projects.