← Back to all tutorials

How to create an animated navigation on scroll with Tailwind CSS and JavaScript

Animated navigation bar
Published on May 14 2024 by Michael Andreuzza

Let’s recreate the navigation bar from the previous tutorial with alpinejs using instead JavaScript and Tailwind CSS.

Why animate the navigation bar though?

An animated navigation bar can add a sense of movement and interactivity to a website, making it more engaging and memorable for users. It can also help to guide the user’s attention to specific sections of the site, improving their overall experience. Additionally, animating the navigation bar can make it more visually appealing and consistent with the overall design of the website.

The sctructure

  • class="header" is the main container for the navigation bar. We will this class to target the navigation bar and its contents.
  • transition-all duration-1000 ease-in-out transform: applies a transition effect to the navigation bar, making it smoothly move on scroll.
  • class="site-title" is the title of the website. We use this class to target the title and change its color when the navigation is being animated on scroll.
  • class="nav-link" is the class of the navigation links.

Classes are removed for brevity, but I’ll keep those classes relevant to the tutorial.

<div
  class="transition-all duration-1000 ease-in-out transform header">
  <div>
    <div>
      <span class="site-title"
        > Lexington</span
      >
      <button>
        <!-- SVG Burger goes here -->
      </button>
    </div>
    <nav>
      <a
        href="#_"
        class="nav-link"
        >About</a
      >
      <a
        href="#_"
        class="nav-link"
        >Work</a
      >
      <a
        href="#_"
        class="nav-link"
        >Blog</a
      >
    </nav>
  </div>
</div>

Let’s get to the script

This is the script that will be used to update the navigation bar according to the user’s scroll position. We’ll use the window.addEventListener method to add an event listener to the window object, which will be triggered when the user scrolls the page.

Event Listener for DOM Content Loaded

  • document.addEventListener("DOMContentLoaded", function () {: This is the event listener that will be used to run the code when the DOM is loaded.

Selecting Elements

  • const header = document.querySelector(".header");: This is the code that will be used to get the header element.
  • const navLinks = document.querySelectorAll(".nav-link");: This is the code that will be used to get all the navigation links.
  • const title = document.querySelector(".site-title");: This is the code that will be used to get the title element.

Updating Header

  • updateHeader();: This is the code that will be used to update the header.

Event Listeners

  • window.addEventListener("scroll", function () {: This is the code that will be used to add an event listener to the window object.
  • navLinks.forEach(function (link) {: This is the code that will be used to iterate over the navigation links.
  • link.addEventListener("click", function () {: This is the code that will be used to add an event listener to each navigation link.

Update Header Function

  • function updateHeader() {: This is the code that will be used to define the updateHeader function.
  • const atTop = window.pageYOffset <= 50;: This is the code that will be used to check if the user is scrolling up or down.
  • header.classList.toggle("bg-white", atTop);: This is the code that will be used to toggle the background color of the header.
  • header.classList.toggle("bg-black", !atTop);: This is the code that will be used to toggle the background color of the header.
  • header.classList.toggle("bg-opacity-90", !atTop);: This is the code that will be used to toggle the background opacity of the header.
  • header.classList.toggle("backdrop-blur-xl", !atTop);: This is the code that will be used to toggle the backdrop blur effect of the header.
  • header.classList.toggle("max-w-4xl", !atTop);: This is the code that will be used to toggle the max width of the header.

Update Text Colors Function

  • function updateTextColors(atTop) {: This is the code that will be used to define the updateTextColors function.
  • const textColor = atTop ? "text-black" : "text-white";: This is the code that will be used to get the text color based on the scroll position.
  • navLinks.forEach(function (link) {: This is the code that will be used to iterate over the navigation links.
  • link.classList.remove(atTop ? "text-white" : "text-black");: This is the code that will be used to remove the text color from the navigation links.
  • link.classList.add(textColor);: This is the code that will be used to add the text color to the navigation links.

Update Title Color Function

  • function updateTitleColor(atTop) {: This is the code that will be used to define the updateTitleColor function.
  • title.classList.remove(atTop ? "text-white" : "text-black");: This is the code that will be used to remove the title color from the navigation bar.
  • title.classList.add(atTop ? "text-black" : "text-white");: This is the code that will be used to add the title color to the navigation bar.

The full script

document.addEventListener("DOMContentLoaded", function () {
    const header = document.querySelector(".header");
    const navLinks = document.querySelectorAll(".nav-link");
    const title = document.querySelector(".site-title");

    updateHeader();

    window.addEventListener("scroll", function () {
      updateHeader();
    });

    navLinks.forEach(function (link) {
      link.addEventListener("click", function () {
        updateHeader();
      });
    });

    function updateHeader() {
      const atTop = window.pageYOffset <= 50;
      header.classList.toggle("bg-white", atTop);
      header.classList.toggle("bg-black", !atTop);
      header.classList.toggle("bg-opacity-90", !atTop);
      header.classList.toggle("backdrop-blur-xl", !atTop);
      header.classList.toggle("max-w-4xl", !atTop);
      updateTextColors(atTop);
      updateTitleColor(atTop);
    }

    function updateTextColors(atTop) {
      const textColor = atTop ? "text-black" : "text-white";
      navLinks.forEach(function (link) {
        link.classList.remove(atTop ? "text-white" : "text-black");
        link.classList.add(textColor);
      });
    }

    function updateTitleColor(atTop) {
      title.classList.remove(atTop ? "text-white" : "text-black");
      title.classList.add(atTop ? "text-black" : "text-white");
    }
  });

Conclusion

In this tutorial, we learned how to create an animated navigation bar using JavaScript and Tailwind CSS. We used the window.addEventListener method to add an event listener to the window object, which triggered the updateHeader function when the user scrolled the page. We also used the classList property to toggle the background color, backdrop blur effect, and max width of the header. By combining these techniques, we were able to create a visually appealing and interactive navigation bar that adapts to the user’s scroll position. Remember to make the navigation fully accessible.

Hope you enjoyed this tutorial and have a nice day!

/Michael Andreuzza

Did you like this tutorial? Please share it with your friends!

Reviews and opinions

  • "I bought a beautiful theme from Lexington a couple weeks ago. I didn't know Astro at the time, but Michael helped me get set up and really went above and beyond with his support. Now I'm happily redoing my site to look gorgeous with his template."

    Stuart

    Stuart

    Creator of saasydb.com

  • "Michael is one of the best designers on Twitter, would highly recommend his Lexington Themes if you want something in tailwind that doesn’t look the same as everyone else!"

    Alex Hughes

    Alex Hughes

    letsloopin.com

Get lifetime access to every theme available today for $199 and own them forever. Plus, new themes, lifetime updates, use on unlimited projects and enjoy lifetime support.

No subscription required!

Lexington

Beautifully designed HTML, Astro.js and Tailwind themes! Save months of time and build your startup landing page in minutes.