Auto-Hiding Website Header & Footer with jQuery Tutorial

There are plenty of reasons for using a sticky header navigation in your website. It provides easy access for top-priority links, plus a way back to the homepage from anywhere on the site. However problems may arise when you have a navigation bar which blocks some of the page content.

In this tutorial I want to demonstrate how we can build a locking header bar which will auto-hide itself after scrolling down the page. Also when scrolling to the very bottom we will display a small footer which includes many of the same nav links.

This technique can be used in almost any website interface to improve readability and general user experience.

Building the Framework

We need to start out with a basic HTML5 template using a fixed header and a basic content area. For this demo I have included a series of external third party scripts hosted from Google’s CDN. This includes a couple web fonts along with the jQuery and jQuery UI libraries.

<!doctype html>
<html lang="en-US">
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
  <title>Auto-Hiding Header Demo Page</title>
  <meta name="author" content="Jake Rocheleau">
  <link rel="shortcut icon" href="">
  <link rel="icon" href="">
  <link rel="stylesheet" type="text/css" media="all" href="styles.css">
  <link rel="stylesheet" type="text/css" media="all" href="|Leckerli+One">
  <script type="text/javascript" src=""></script>
  <script type="text/javascript" src=""></script>
  <script type="text/javascript" language="javascript" charset="utf-8" src="autohide.js"></script>

You may notice we also need a third local JavaScript file named autohide.js. This will provide all the JS codes we need to animate and hide/show the header block.

Let’s take a brief look at the content structure to understand how I have laid out the individual div blocks.

<div id="headwrapper">
  <div id="fixedheader">
    <header id="top">
      <div id="logo">
        <!-- Logo Source: -->
        <h1><a href="index.html"><img src="" alt="AutoHide Header"></a></h1>
        <h2>intelligent auto-hide effect</h2>
        <ul id="rightlinks">
          <li><a href="javascript:void(0)">Register</a></li> - 
          <li><a href="javascript:void(0)">Login</a></li> - 
          <li><a href="javascript:void(0)">FAQ/Wiki</a></li> - 
          <li><a href="javascript:void(0)">Support</a></li>
      <nav id="topnav">
          <li><a href="javascript:void(0)">Homepage</a></li>
          <li><a href="javascript:void(0)">About Us</a></li>
          <li><a href="javascript:void(0)">Publications</a></li>
          <li><a href="javascript:void(0)">Authors</a></li>
          <li><a href="javascript:void(0)">Other Projects</a></li>
          <li><a href="javascript:void(0)">Get In Touch</a></li>
  </div> <!-- /end #fixedheader -->
</div> <!-- /end #headwrapper -->

There are a fairly large number of nested divs in the header area so I will explain the structure first. T

he outermost container #headwrapper is given the limited width 780px and a margin: 0 auto; property in CSS. This will center the entire header on the page. Inside is a div #fixedheader which is actually the main fixed item.

This container needs to use a grey background and be pushed up into the top of the page using negative positioning. As the header animates upwards it will first pull down a bit, and without this container we just see the background behind it.

The internal <header> element is the “official” container which holds both the logo and navbar. You can see this brief pull-down effect in the live demo page.

Base CSS Styles

Aside from the inner content we do not need to learn much else about the HTML. All of the internal content areas are pushed exactly enough pixels to meet edge-to-edge with the header. It is much easier to explain how we can style the layout, beginning with a few CSS resets.

html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
  outline: none;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
html { height: 101%; }
body {background: #a4b1c2; font-family: Tahoma, Arial, sans-serif; font-size: 62.5%; line-height: 1; }

::selection { background: #f2c6dc; color: #111; }
::-moz-selection { background: #f2c6dc; color: #111; }
::-webkit-selection { background: #f2c6dc; color: #111; }

br { line-height: 1.95em; }

article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; }
ol, ul { list-style: none; }

blockquote, q { quotes: none; }
blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; }
strong { font-weight: bold; } 

table { border-collapse: collapse; border-spacing: 0; }
img { border: 0; max-width: 100%; }

a { color: #7091c7; }
a:hover { color: #4e72ad; }

Our topmost code is a mixed template I put together for this tutorial which includes a few useful style resets. We are adding the <br> tag selector to increase the size of line breaks, and also CSS3 anti-aliasing on rendered text and various highlighted text effects. Another big point is how we are structuring the overall page to center within the layout.

I am using 2 different wrappers for containing the header and the body. This offers an easier solution to separate content and even merge the idea into a full-width layout. The logo sections and top navigation bar are put together to work as a fluid design, even though this particular layout is fixed-width.

/* page structure */
#fixedheader {
  display: block;
  position: fixed;
  top: -35px;
  padding-top: 25px;
  margin: 0;
  height: auto;
  width: 780px;
  background: #303030;
  z-index: 9999;
  -webkit-box-shadow:  0 -3px 4px 0px #222;
  -moz-box-shadow:  0 -3px 4px 0px #222;
  box-shadow: 0 -3px 4px 0px #222;

#pagewrapper {
  display: block;
  position: relative;
  width: 780px;
  background: #fff;
  padding: 0;
  margin: 0 auto;
  margin-top: 117px;
  -webkit-box-shadow:  0 3px 7px -1px #222;
  -moz-box-shadow:  0 3px 7px -1px #222;
  box-shadow: 0 3px 7px -1px #222;

#headwrapper {
  display: block;
  width: 780px;
  background: #fff;
  padding: 0;
  margin: 0 auto;

/* top header */
#top {
  display: block;
  position: relative;
  width: 780px;
  padding: 0;
  margin: 0;
  top: 0;
  z-index: 9999;
  background: #303030;
  border-bottom: 3px solid #414d65;

#logo {
  display: block;
  width: 100%;
  height: 82px;
  top: 0;
  padding: 0 12px;
  background-color: #111;
  background-image: -webkit-gradient(linear, left top, left bottom, from(#303030), to(#111));
  background-image: -webkit-linear-gradient(top, #303030, #111);
  background-image: -moz-linear-gradient(top, #303030, #111);
  background-image: -ms-linear-gradient(top, #303030, #111);
  background-image: -o-linear-gradient(top, #303030, #111);
  background-image: linear-gradient(top, #303030, #111);

/* navigation bar */
#topnav {
  display: block;
  border-top: 1px solid #839aca;
  background: #485c86;
  background-image: -webkit-gradient(linear, left top, left bottom, from(#5f739d), to(#485c86));
  background-image: -webkit-linear-gradient(top, #5f739d, #485c86);
  background-image: -moz-linear-gradient(top, #5f739d, #485c86);
  background-image: -ms-linear-gradient(top, #5f739d, #485c86);
  background-image: -o-linear-gradient(top, #5f739d, #485c86);
  background-image: linear-gradient(top, #5f739d, #485c86);
  height: 32px;

#topnav ul {
  padding: 0 10px;

#topnav ul li { display: inline; font-size: 1.2em; }

#topnav ul li a {
  display: block;
  float: left;
  line-height: 31px;
  padding: 0 7px;
  margin-right: 6px;
  color: #d1dfeb;
  font-weight: bold;
  text-decoration: none;
  -webkit-transition: all 0.4s linear;
  -moz-transition: all 0.4s linear;
  transition: all 0.4s linear;
#topnav ul li a:hover {
  background: rgba(255,255,255,0.2);
  text-shadow: 1px 1px 0 rgba(0,0,0,0.2);

Notice a lot of these codes are using CSS3 properties for gradients and transition effects. It helps to go the extra mile and spice up your design with these features. Most browsers can handle the properties, and the fallback solutions are just natively rendering properties, so it isn’t much of a downgrade.

#toparrow {
  display: none;
  width: 130px;
  height: 130px;
  position: fixed;
  bottom: 45px;
  right: 45px;
  cursor: pointer;
  background: url('') 0 0 no-repeat;
  z-index: 9999; 

This last block of code targets the top arrow icon I’ve added into the page. This div is fixed onto the right side and will only appear after the header is hidden. This solution allows users to click for an instant jump up to the top of the page. It can be easier than scrolling in most cases.

Animating the Header & Footer

Inside the JS file we are putting together numerous logic statements. It is listening for the window scroll event and firing various functions depending on the circumstances. I have included source comments with each of the if{} statements to help clarify what we are checking. Let’s break it down into three major sections.

  var timer;
  $(window).scroll(function() {

    var topdisplay  = $('#fixedheader').css('top');
    var footdisplay = $('#fixedfooter ul').css('display');
    var scrolltoppx = $(this).scrollTop();

This is the first piece which contains an event listener and some new variable definitions. topdisplay will check the current status of our header’s top property in CSS. We set the default position value at -35px, so in this case the header would be visible. Otherwise we have it hidden, and need to readjust back to -35px via animation.

The second variable footdisplay will check the display property of our footer. This will be needed for the logic of checking whether to display or hide the bottom footer element. Also we will need scrolltoppx which holds a numerical value in pixels of the total distance from the top of the screen. It will update with every user scroll event.

if(scrolltoppx < 10 && topdisplay != "-35") {
      // if we scroll up anywhere from 9px-0px and the header is hidden,
      // immediately display the header smoothly into the scroll

    if(scrolltoppx > 130 && topdisplay == "-35") {
      // if we scroll beyond 130px and the header is still displaying,
      // hide the header after 700ms pause
      timer = setTimeout(function() {
      }, 600);

Now here is the first big chunk of logic statements for calling our pre-defined functions.

The first statement checks if the header is not at -35px and we scroll back towards the top area; we need to display the header. We do so by calling a function autoDisplayHeader() which is written a bit later in the JavaScript file.

Similarly if we scroll beyond 130px and the header is still displayed, we need to hide it. This uses a different function named autoHideHeader(). But notice this code is contained inside a JavaScript function setTimeout(). After the user stops scrolling we pause for 600ms and then hide the header, simultaneously displaying the “back to top” arrow.

    if(scrolltoppx + $(window).height() == getDocHeight()) {
      // if the current window position + the above space equals the total window height
      // then the user is at the bottom of the page.
      // in this case we quickly display the small fixed footer
      if(footdisplay == 'none') {
        $('#fixedfooter ul').fadeIn(300);
    if(scrolltoppx + $(window).height() != getDocHeight() && footdisplay == 'block') {
      // if the user is not at the bottom and our footer is being displayed
      // we need to hide it until we re-enter the bottom again
      $('#fixedfooter ul').fadeOut(300);


  $('#toparrow').on('click', function() {
    // when clicking the arrow we are animated immediately to the top
    $("html, body").animate({ scrollTop: "0" });

These last few statements refer to the footer block.

We are putting together the user’s current placement on the screen added to the rest of the page height. This should equal the full window height, which is provided via a custom function getDocHeight(). This is not my own function but originally written by James Padolsey for the purpose of supporting a greater number of older legacy browsers.

The other logic statement is checking the reverse, and auto-hiding our footer once we scroll away from the bottom.

And finally the last clause is listening for when the user clicks on the #toparrow div. Notice that we are now outside of the scrolling event handler; so these are the only 2 event listeners which trigger some type of response on the page.

All of the custom functions are easy enough to understand with a bit of studying. But I have copied them below in case you are interested.

 * functions to hide and display the header
function autoHideHeader(){
    top: '-149px',
  }, 450, 'easeInBack');
    'margin-top': '3px',
  }, 450, 'easeInBack');  
function autoDisplayHeader(){
    top: '-35px',
  }, 400, 'easeOutBack');
    'margin-top': '117px',
  }, 400, 'easeOutBack');  

 * cross-browser function to determine full browser height
 * needed to check when user hits the bottom of the webpage
 * source:
function getDocHeight() {
  var D = document;
  return Math.max(
    Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
    Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
    Math.max(D.body.clientHeight, D.documentElement.clientHeight)

In older browsers where JavaScript is disabled there isn’t much of a loss for users. The header navigation will always stay fixed regardless of scrolling distance. So this extra technique just provides a bit of finesse to your website interface. It is also a convenience for the user to have an uncluttered browsing experience.

Be sure and check out my live demo to get a bigger picture of the whole web application.

jquery ui animated header footer autohiding intelligent tutorial

Final Thoughts

I hope this tutorial may provide some useful ideas to web developers. Many of these codes are re-usable with just a few customizations to the CSS. But you should download a copy of my demo project codes to save this working template as a resource.

Additionally if you have any thoughts or questions on the tutorial feel free to share with us in the post discussion area.