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!
Frequently Asked Questions about Animated Sticky Navigation Menu in JavaScript
How can I make my navigation menu sticky in JavaScript?
Making a navigation menu sticky in JavaScript involves using the position property in CSS. You can set the position of your navigation menu to ‘sticky’ and specify the top value to 0. This will make the navigation menu stick to the top of the page when you scroll down. Here’s a simple example:var menu = document.querySelector('#myMenu');
window.onscroll = function() {
if (window.pageYOffset > 100) {
menu.style.position = 'fixed';
menu.style.top = '0';
} else {
menu.style.position = 'relative';
}
};
This code will make the menu stick to the top of the page when you scroll more than 100 pixels down.
How can I animate my navigation menu in JavaScript?
Animating a navigation menu in JavaScript can be achieved using CSS transitions or the animate() method in jQuery. For instance, you can use the transition property in CSS to animate the height of the menu:#myMenu {
transition: height 2s;
}
Then, in your JavaScript code, you can change the height of the menu when a certain event occurs, like clicking a button:var button = document.querySelector('#myButton');
button.onclick = function() {
var menu = document.querySelector('#myMenu');
menu.style.height = '200px';
};
This will animate the height of the menu from its current height to 200 pixels over 2 seconds when the button is clicked.
How can I create a dropdown menu in JavaScript?
Creating a dropdown menu in JavaScript involves creating a list of links or items that are hidden by default and then showing them when a certain event occurs, like hovering over or clicking on the menu. Here’s a simple example:<div id="myMenu">
<button>Menu</button>
<div id="myDropdown">
<a href="#">Link 1</a>
<a href="#">Link 2</a>
<a href="#">Link 3</a>
</div>
</div>
#myDropdown {
display: none;
}
var button = document.querySelector('#myMenu button');
button.onclick = function() {
var dropdown = document.querySelector('#myDropdown');
dropdown.style.display = 'block';
};
This will show the dropdown menu when the button is clicked.
How can I create a burger menu animation in JavaScript?
Creating a burger menu animation in JavaScript involves changing the appearance of the burger icon when the menu is opened or closed. This can be achieved by rotating and moving the lines of the burger icon. Here’s a simple example:<div id="myBurger">
<div></div>
<div></div>
<div></div>
</div>
#myBurger div {
width: 35px;
height: 5px;
background-color: #333;
margin: 6px 0;
transition: 0.4s;
}
var burger = document.querySelector('#myBurger');
burger.onclick = function() {
for (var i = 0; i < burger.children.length; i++) {
var line = burger.children[i];
line.style.transform = 'rotate(45deg)';
line.style.marginTop = '10px';
}
};
This will rotate the lines of the burger icon 45 degrees and move them 10 pixels from the top when the burger is clicked, creating a cross animation.
How can I create a sliding menu in JavaScript?
Creating a sliding menu in JavaScript involves changing the position of the menu from off the screen to on the screen when a certain event occurs, like clicking a button. This can be achieved using the transform property in CSS. Here’s a simple example:<div id="myMenu">Menu</div>
<button id="myButton">Open Menu</button>
#myMenu {
transform: translateX(-100%);
transition: transform 0.5s;
}
var button = document.querySelector('#myButton');
button.onclick = function() {
var menu = document.querySelector('#myMenu');
menu.style.transform = 'translateX(0)';
};
This will slide the menu from the left side of the screen to its original position when the button is clicked.
![Albert Senghor](https://uploads.sitepoint.com/wp-content/uploads/2017/05/1493896391s1457191635_30008660_1323_400x400-96x96.jpg)
Albert is a JavaScript/React enthusiast. He enjoys making great web products with the latest technologies.