JavaScript - - By Albert Senghor

Create an Animated Sticky Navigation Menu with Vanilla JavaScript

When adding a navigation menu to a webpage, there are a lot of things to take into consideration. For example where to position it, how to style it, how to make it responsive. Or maybe you want to add some kind of animation to it (tastefully, of course). At this point you might be tempted to grab a jQuery plugin which does most of that for you. But that needn’t be! It’s actually pretty simple to create your own solution in a few lines of code.

In this post, I will demonstrate how to create an animated, sticky navigation menu with vanilla JavaScript, CSS and HTML. The final product will slide up out of your way as you scroll down the page, then slide back into view (with a stylish see-through effect) when you scroll back up. This is a technique used by such popular sites, such as Medium and Hacker Noon.

After reading you’ll be able to employ this technique in your own designs, hopefully to great effect. There’s a demo at the end of the article for the impatient.

The following is the skeleton HTML code that we will be working with. Nothing too exciting going on here.

<div class="container">
  <div class="banner-wrapper">
    <div class="banner">
      <div class="top">
        <!-- Navbar top row-->
      </div>
      <div class="nav">
        <!-- Links for navigation-->
      </div>
    </div>
  </div>

  <div class="content">
    <!-- Awesome content here -->
  </div>
</div>

Applying a Little Styling

Let’s add some styling to the main elements.

Main Container

We’ll need to remove any inherent browser styles and set the width of our container to 100%.

*{
  box-sizing:border-box;
  padding: 0;
  margin: 0;
}

.container{
  width: 100%;
}

Banner Container

This is a wrapper around the navigation menu. It is always sticky and slides to hide or reveal the navigation menu as you scroll your page vertically. We are giving it a z-index value to ensure that it appears on top of the content.

.banner-wrapper {
  z-index: 4;
  transition: all 300ms ease-in-out;
  position: fixed;
  width: 100%;
}

Banner Section

This contains the navigation menu. Changes in position and background color are animated through the CSS transition property when a page is scrolled up or down.

.banner {
  height: 77px;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  background: rgba(162, 197, 35, 1);
  transition: all 300ms ease-in-out;
}

Content Section

This section will contain a background image and text. We will add a parallax effect to this part of the page in a later section of the article.

.content {
  background: url(https://unsplash.it/1400/1400?image=699) center no-repeat;
  background-size: cover;
  padding-top: 100%;
}

Animating the Menu

The first thing we need to do is to attach an event handler to the scroll event, so that we can show and hide the menu accordingly when the user scrolls. We’ll also enclose everything in an IIFE so as to avoid clashes with other code running on the same page.

(() => {
  'use strict';

  const handler = () => {
    //DOM manipulation code here
  };

  window.addEventListener('scroll', handler, false);
})();

Setting Some Initial Values

We’ll be using a refOffset variable to represent the amount of distance the user has scrolled down the page. This is initialized to 0 on page load. We’ll use a bannerHeight variable to store the menu’s height and will also need references to the .banner-wrapper and .banner DOM elements.

let refOffset = 0;
let visible = true;
const bannerHeight = 77;

const bannerWrapper = document.querySelector('.banner-wrapper');
const banner = document.querySelector('.banner');

Establishing Scroll Direction

Next we need to establish scroll direction so that we can show or hide the menu accordingly.

We’ll start off with a variable called newOffset. On page load this will be set to the value of window.scrollY — the number of pixels that the document is currently scrolled vertically (so 0 initially). When a user scrolls, newOffset will increase or decrease accordingly. If it is greater than the value stored in bannerHeight then we know our menu has been scrolled out of view.

const newOffset = window.scrollY;

if (newOffset > bannerHeight) {
  // Menu out of view
} else {
  // Menu in view
}

Scrolling down will make newOffset greater than refOffset and the navigation menu should slide up and disappear. Scrolling up will make newOffset less than refOffset and the navigation menu should slide back into view with a see through effect. After performing this comparison, we will need update refOffset with the value of newOffset to keep track of how far the user has scrolled.

if (newOffset > bannerHeight) {
  // Menu out of view
  if(newOffset > refOffset) {
    // Hide the menu
  } else if (newOffset < refOffset) {
    // Slide menu back down
  }

  refOffset = newOffset;
} else {
  // Menu in view
}

Animating the Menu

Finally, let’s add some animation to show and hide the menu. We can do this using the following CSS:

.animateIn{
  transform: translateY(0px);
}

.animateOut{
  transform: translateY(-100%);
}

We should also make sure that the see-through effect is removed from the menu once the top of page is reached.

if (newOffset > bannerHeight) {
  if (newOffset > refOffset) {
    bannerWrapper.classList.remove('animateIn');
    bannerWrapper.classList.add('animateOut');
  } else {
    bannerWrapper.classList.remove('animateOut');
    bannerWrapper.classList.add('animateIn');
  }
  banner.style.background = 'rgba(162, 197, 35, 0.6)';
  refOffset = newOffset;
} else {
  banner.style.backgroundColor = 'rgba(162, 197, 35, 1)';
}

As you can see, we are removing/appling the different CSS classes accordingly.

Demo

Here is a demo of the working menu.

See the Pen ZKJVdw by SitePoint (@SitePoint) on CodePen.

Conclusion

This article has described how you can design an animated navigation menu in a few lines of code using just vanilla JavaScript — no jQuery needed. The menu slides to disappear when you scroll down and slides back into view with a transparency effect when you scroll back up. This is done by monitoring the vertical scroll direction and applying CSS transformations to the DOM element as required. Such a custom solution gives you more freedom to easily and flexibly design according to your own requirements and specifications.

Want to up your JavaScript skills? Check out our courses Introduction to JavaScript and
JavaScript: Next Steps
.

This article was peer reviewed by Vildan Softic. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

Sponsors