Create a navigation bar with an animated indicator

Have you always wanted a dynamic navigation bar with an indicator that glides smoothly underneath the new page you're on? This navigation bar is exactly what you need!
•
Updated on August 14, 2026
•
5 min read
Believemy logo

You have always wanted to create a dynamic navigation bar with an indicator that smoothly slides underneath the new page you are on? This navigation bar is exactly what you need!

Image showing our menu

 

Step 1: The HTML Code

To begin, let's create the HTML code that will allow us to set up our navigation bar.

HTML
<nav>
  <a href="#">Home</a>
  <a href="#">About</a>
  <a href="#">Testimonials</a>
  <a href="#">Blog</a>
  <a href="#">Contact</a>
</nav>

Nothing too difficult to understand here. We have a <nav></nav> tag grouping several links. Let's add a class .nav-item to each link so that our different links can be styled more easily. We will then create a class with the same name to add some properties.

HTML
<nav>
  <a href="#" class="nav-item is-active">Home</a>
  <a href="#" class="nav-item">About</a>
  <a href="#" class="nav-item">Testimonials</a>
  <a href="#" class="nav-item">Blog</a>
  <a href="#" class="nav-item">Contact</a>
</nav>

Note that we have also added a .is-active class so that the current page is displayed differently. This is a visual marker that is very useful.

 

Step 2: The CSS Code

For our styling, we start with very simple code. Follow the comments to understand what we're doing.

CSS
/* Ensure each element includes its internal margin with box-sizing and remove the default link underlines */
* {
  box-sizing: border-box;
  text-decoration: none;
}

/* Modernize our navigation bar with a subtle shadow. Arrange all menu items side by side using flexbox (display: flex) */
nav {
  background-color: #fff;
  padding: 0 20px;
  border-radius: 40px;
  box-shadow: 0 10px 40px rgba(159, 162, 177, .8);
  display: flex;
  overflow: hidden;
  overflow-x: auto;
  position: relative;
}

/* Style each item */
.nav-item {
  color: #83818c;
  font-family: Arial, sans-serif;
  padding: 20px;
  margin: 0 6px;
  position: relative;
}

/* Here we add a small element before each item to make it visually appealing */
.nav-item:before {
  content: "";
  position: absolute;
  bottom: -6px;
  background-color: #dfe2ea;
  height: 5px;
  width: 100%;
  border-radius: 8px 8px 0 0;
  left: 0;
  transition: .3s;
}

/* With the latest CSS features, we can change the properties of elements based on conditions using :not */
.nav-item:not(.is-active):hover:before {
  bottom: 0;
}
.nav-item:not(.is-active):hover {
  color: #333;
}

/* Style our indicator */
.nav-indicator {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 5px;
  transition: .4s;
  border-radius: 8px 8px 0 0;
}

 

Step 3: Finalize the HTML Part

Having a menu is great! But let's now try to modernize it with an indicator that moves according to the current page.

To achieve this, let's start by adding an HTML element using the <span></span> tag inside our navigation bar to include an element that will move based on our current page.

HTML
<nav>
  <a href="#" class="nav-item is-active" data-active-color="orange" data-target="Home">Home</a>
  <a href="#" class="nav-item" data-active-color="green" data-target="About">About</a>
  <a href="#" class="nav-item" data-active-color="blue" data-target="Testimonials">Testimonials</a>
  <a href="#" class="nav-item" data-active-color="red" data-target="Blog">Blog</a>
  <a href="#" class="nav-item" data-active-color="rebeccapurple" data-target="Contact">Contact</a>
  <span class="nav-indicator"></span>
</nav>

We have almost finished our HTML! Let's finish by adding data attributes that can be retrieved by our JavaScript code: simply use data attributes by specifying the desired name:

HTML
<nav>
  <a href="#" class="nav-item is-active" data-active-color="orange" data-target="Home">Home</a>
  <a href="#" class="nav-item" data-active-color="green" data-target="About">About</a>
  <a href="#" class="nav-item" data-active-color="blue" data-target="Testimonials">Testimonials</a>
  <a href="#" class="nav-item" data-active-color="red" data-target="Blog">Blog</a>
  <a href="#" class="nav-item" data-active-color="rebeccapurple" data-target="Contact">Contact</a>
  <span class="nav-indicator"></span>
</nav>

Our code is complete! Now let's move on to the JavaScript.

 

Step 4: The JavaScript Code

To start, it's very important to select our indicator and each of our items:

JAVASCRIPT
const indicator = document.querySelector('.nav-indicator');
const items = document.querySelectorAll('.nav-item');

Once our elements have been selected, we will detect events. What interests us most is the click event.

Good to know

The JavaScript property querySelectorAll returns a NodeList that contains each of our items.

Therefore, all that's left is to use a forEach loop to attach the event listener using addEventListener, specifying that we want to call the handleIndicator function.

This new handleIndicator function will allow us to detect the link that was clicked to move the indicator (indicator).

JAVASCRIPT
const indicator = document.querySelector('.nav-indicator');
const items = document.querySelectorAll('.nav-item');

function handleIndicator(el) {
  
}

items.forEach((item, index) => {
  item.addEventListener('click', e => {
    handleIndicator(e.target)
  });
  item.classList.contains('is-active') && handleIndicator(item);
});

All that remains is to create the handleIndicator function.

JAVASCRIPT
const indicator = document.querySelector('.nav-indicator');
const items = document.querySelectorAll('.nav-item');

function handleIndicator(el) {
  // Loop through items and remove the "is-active" class
  items.forEach(item => {
    item.classList.remove('is-active');
    item.removeAttribute('style');
  })
  
  const elementColor = el.dataset.activeColor;
  const target = el.dataset.target;
  
  // Style the indicator
  indicator.style.width = `${el.offsetWidth}px`;
  indicator.style.backgroundColor = elementColor;
  indicator.style.left = `${el.offsetLeft}px`;
  
  // Add the "is-active" class
  el.classList.add('is-active');
  el.style.color = elementColor;
}

items.forEach((item, index) => {
  item.addEventListener('click', e => {
    handleIndicator(e.target)
  });
  item.classList.contains('is-active') && handleIndicator(item);
});

Here's what we do for each clicked element:

  • Remove the .is-active class from all elements: we reset the menu;
  • Retrieve the color of the clicked item using dataset, which allows us to read the data attribute;
  • Use this color to define the style of our indicator (indicator);
  • Finally, add the .is-active class to the current page's element.

And that's it!

If you want to learn more, don't hesitate to follow our dedicated courses on JavaScript or React (if you are well-versed in JavaScript) to fully take advantage of your brand new menu created in this article!

Category: Developers

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.

Believemy logo
Comments (0)

You need to be logged in to comment on this article: log in or sign up.

Read next

Make an animated notification message with JavaScript

Whether it's to quickly warn your users that a feature of your site is not yet available or to let them know that an action has been successfully completed, notifications are the simplest and most modern way to set up. Find out how in this article!

December 9, 2024

Create a menu that spans the entire page using CSS

From time to time we have to ask our visitors which page they want to go to, by displaying the main sections of our website. This menu is often not very pleasant to use, so let's find out together in this article how to make it much more modern, with beautiful animations that will make your passers-by want to visit your site!

December 9, 2024

Creating an animated list with CSS

Let's find out how to create an animated hover list!

December 9, 2024

Create an animated "rainbow" button with CSS

In this article, we'll show you how to create a rainbow button that comes to life when the mouse hovers over it. A modern and sensational effect guaranteed!

December 9, 2024

Create an animated gradient background on hover avec CSS

Whether it's to highlight a part of your website or a quote as in this example, generating and adding a gradient to the background can give your website a very modern touch. Find out in this article how to do it easily!

December 9, 2024

Create a clean, modern timeline using html and css

Whether you want to show a purchasing process, the highlights of your career on your portfolio, or anything else, learn how to create a sleek, modern timeline to show it off!

December 9, 2024

Creating circled buttons on hover with HTML and CSS

For a menu or to encourage your readers to share your website, share buttons are essential elements to add to your website. Let's find out how to make them more modern with a "neon" effect that will surround the icon selected by your user.

December 9, 2024

Creating an "Old School" button with CSS

Let's find out how to create an original button that's right up to date!

December 9, 2024

Become the solopreneur you dream of being.

First project, career change, business launch: access our courses, practice on real-world cases, and move forward with clear guidance.