December 6, 2015

Hide div on scroll down, show on scroll up

Hide div on scroll down, show on scroll up

Fixed headers are fairly common nowadays with big name brands. More and more people are using mobile phones where screen real estate is a commodity. Even on desktops and tablets applications that get out of the way and let users focus on content feel better. There’s more room to breathe; your eyes don’t feel like squinting.

How can we improve on the fixed header pattern? Here’s a proposal: hide the header as the user scrolls down, and show it again when the user scrolls up. This is not revolutionary. Other apps and websites are already doing this, and it’s pretty sweet. Here’s how you do it.

We’re going to achieve this effect using CSS3 transitions and just a tad of JavaScript. The basic idea is this:

  1. set the header to position fixed
  2. on scroll down, add a class to move the header up
  3. on scroll up, remove the class to show the header again

HTML

<header></header>
<main></main>
<footer></footer>

CSS

body {
  padding-top: 40px; // same as header height
}
header {
  background: #f5b335;
  height: 40px;
  position: fixed;
  top: 0;
  transition: top 0.2s ease-in-out;
  width: 100%;
}
// we'll add this class using javascript
.nav-up {
  top: -40px; // same as header height. use variables in LESS/SASS
}

Let’s start off by saying that attaching functions to scroll events can be very expensive to performance. We’ll remedy this by checking if the user has scrolled on an interval instead of executing functions for every pixel scrolled.

Javascript

var didScroll;
// on scroll, let the interval function know the user has scrolled
$(window).scroll(function(event){
  didScroll = true;
});
// run hasScrolled() and reset didScroll status
setInterval(function() {
  if (didScroll) {
    hasScrolled();
    didScroll = false;
  }
}, 250);
function hasScrolled() {
  // do stuff here...
}

On $(window).scroll, all we do is set the variable didScroll to true. The interval checks every 250ms if didScroll has changed. If it has, it runs the function and resets didScroll to false. It’s much easier for the browser to set a boolean variable than to run through a whole set of functions for every pixel scrolled.

To hide the header, we’ll determine the following:

  1. if they scrolled more than delta
  2. if they scrolled past the header height
  3. if they scrolled past the header height
  4. store the current scroll position in a variable

Let’s start out by defining all variables at the top.

var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $(‘header’).outerHeight();

Inside hasScrolled(), store the scroll position in a variable for easy access.

var st = $(this).scrollTop();

Check if they scrolled more than delta.

if (Math.abs(lastScrollTop — st) <= delta)
  return;

Check if they scrolled past the header and if they scrolled up or down.

// If current position > last position AND scrolled past navbar...
if (st > lastScrollTop && st > navbarHeight){
  // Scroll Down
  $(‘header’).removeClass(‘nav-down’).addClass(‘nav-up’);
} else {
  // Scroll Up
  // If did not scroll past the document (possible on mac)...
  if(st + $(window).height() < $(document).height()) { 
    $(‘header’).removeClass(‘nav-up’).addClass(‘nav-down’);
  }

Set lastScrollTop to the current position.

lastScrollTop = st;

That’s it. It’s as simple as that. Try it and let me know what you think.

Attachments:

Make sure you have jQuery loaded.

//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
demo

No comments:

Post a Comment

Popular Posts

Views