Slide In (as you scroll down) Boxes

Published by Chris Coyier

I was playing with my new Nexus 7 (I really wanted to own a real Android device) and I noticed a neat little effect in the Google+ app that comes with it. As you swipe down, new modules of content slide up into place. Video is best here:

We can do that! It's a pretty easy two-step process:

When the window scrolls, check if module is visible

jQuery has a :visible selector, but that isn't what we need here. We need to see if any part of the element is within the visual viewport. That is, an element may be technically visible, but located off-screen. We can figure out if an element is within the visual viewport through math. How wide and tall is the window, how far down is it scrolled, how wide and tall is the element, where is it positioned, etc. Fortunately that math is summed up super nicely by the visible plugin by Digital Fusion.

(function($) {

  /**
   * Copyright 2012, Digital Fusion
   * Licensed under the MIT license.
   * http://teamdf.com/jquery-plugins/license/
   *
   * @author Sam Sehnert
   * @desc A small plugin that checks whether elements are within
   *     the user visible viewport of a web browser.
   *     only accounts for vertical position, not horizontal.
   */

  $.fn.visible = function(partial) {
    
      var $t            = $(this),
          $w            = $(window),
          viewTop       = $w.scrollTop(),
          viewBottom    = viewTop + $w.height(),
          _top          = $t.offset().top,
          _bottom       = _top + $t.height(),
          compareTop    = partial === true ? _bottom : _top,
          compareBottom = partial === true ? _top : _bottom;
    
    return ((compareBottom <= viewBottom) && (compareTop >= viewTop));

  };
    
})(jQuery);

All that's left for us is using it when the window "scrolls" to add a class name.

$(window).scroll(function(event) {
  
  $(".module").each(function(i, el) {
    var el = $(el);
    if (el.visible(true)) {
      el.addClass("come-in"); 
    } 
  });
  
});

CSS will handle the slide-in:

.come-in {
  transform: translateY(150px);
  animation: come-in 0.8s ease forwards;
}
.come-in:nth-child(odd) {
  animation-duration: 0.6s; /* So they look staggered */
}

@keyframes come-in {
  to { transform: translateY(0); }
}

If elements are already visible, let them be

So we don't trigger the animation on the already visible modules on the very first swipe, we'll add a class name to remove that animation. And we can get a bit more efficient here too, "caching" selectors so we don't have to find them on each scroll event (which fires tons of times).

var win = $(window);
var allMods = $(".module");

// Already visible modules
allMods.each(function(i, el) {
  var el = $(el);
  if (el.visible(true)) {
    el.addClass("already-visible"); 
  } 
});

win.scroll(function(event) {
  
  allMods.each(function(i, el) {
    var el = $(el);
    if (el.visible(true)) {
      el.addClass("come-in"); 
    } 
  });
  
});

That'll do:

Check out this Pen!

And note, the CSS transition could be anything. They could slide in from the sides, they could use scaling and opacity and look like they were flying in. There could be color involved. Whatevs.