Vanilla Javascript: Creating Animated Sticky Navigation Menu
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.
Sticky Navigation Menu: Basic HTML Structure
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!