Responsive Navigation Bar With Tailwind CSS And A Drop Of Javascript

Responsive Navigation Bar With Tailwind CSS And A Drop Of Javascript


Dec 03 2018, 15:19 in Web Development

I've recently switched to Tailwind CSS and I must say it's really good ! Mainly because you can build anything and you have much more freedom than if you were using Bootstrap or Bulma.

As for bulma.io, tailwind css does not provide any Javascript. In many case it's fine, but the one trouble I've had was to build a Responsive Navbar with hamburger toggle in mobile. At this point you need javascript.

If you're using VueJS you might be tempted to wrap your navigation bar in a Vue Component and simply toggle one property when clicking the hamburger. While this is obviously a good way to go for a Single Page Application, you will have one issue if you're only using a few VueJS components in your server side rendered layout (blade files for laravel). Why ? Because you need VueJS to load before the navigation appears. That will cause your entire page to "flash" when loading the page.

So let's drop the Vue Component wrapper. Why not use a single .js file with a few line of vanilla javascript? That's super fast, does not rely on anything, and you don't need to ever touch this file again! You can then re-import this file into all your projects.

First we will build the html template of our navigation:

<div class="border-b border-indigo-darkest bg-teal py-4 px-2">
    <div class="container mx-auto">
        <nav class="flex items-center justify-between flex-wrap">
            <div class="flex items-center flex-no-shrink text-white mr-6">
              <svg class="fill-current h-8 w-8 mr-2" width="54" height="54" viewBox="0 0 54 54" xmlns="http://www.w3.org/2000/svg"><path d="M13.5 22.1c1.8-7.2 6.3-10.8 13.5-10.8 10.8 0 12.15 8.1 17.55 9.45 3.6.9 6.75-.45 9.45-4.05-1.8 7.2-6.3 10.8-13.5 10.8-10.8 0-12.15-8.1-17.55-9.45-3.6-.9-6.75.45-9.45 4.05zM0 38.3c1.8-7.2 6.3-10.8 13.5-10.8 10.8 0 12.15 8.1 17.55 9.45 3.6.9 6.75-.45 9.45-4.05-1.8 7.2-6.3 10.8-13.5 10.8-10.8 0-12.15-8.1-17.55-9.45-3.6-.9-6.75.45-9.45 4.05z"/></svg>
              <span class="font-semibold text-xl tracking-tight">Tailwind CSS</span>
            </div>
            <div class="block sm:hidden">
                <button class="navbar-burger flex items-center px-3 py-2 border rounded text-white border-white hover:text-white hover:border-white">
                    <svg class="fill-current h-3 w-3" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><title>Menu</title><path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"/></svg>
                </button>
            </div>
            <div id="main-nav" class="w-full flex-grow sm:flex items-center sm:w-auto hidden">
                <div class="text-sm sm:flex-grow">
                    <a href="#" class="no-underline font-bold block mt-4 sm:inline-block sm:mt-0 text-grey-lighter hover:text-grey-light mr-4">
                        Link One
                    </a>
                    <a href="#" class="no-underline font-bold block mt-4 sm:inline-block sm:mt-0 text-grey-lighter hover:text-grey-light mr-4">
                        Link Two
                    </a>
                </div>
                <div>
                  <a href="#" class="no-underline inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal hover:bg-white lg:mt-0">Download</a>
                </div>
            </div>
        </nav>
    </div>
</div>

There are only two important things to note here:

  • The "main-nav" id which will be hidden on mobile per default, and will be toggled to visible when clicking the burger
  • The "navbar-burger" class that will be binded to the click event.

Those 2 can be renamed to whatever you like as they are not tailwind classes.

No we can use a few lines of vanilla javascript to toggle the class of the main-nav

// Navbar Toggle
document.addEventListener('DOMContentLoaded', function () {

  // Get all "navbar-burger" elements
  var $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);

  // Check if there are any navbar burgers
  if ($navbarBurgers.length > 0) {

    // Add a click event on each of them
    $navbarBurgers.forEach(function ($el) {
      $el.addEventListener('click', function () {

        // Get the "main-nav" element
        var $target = document.getElementById('main-nav');

        // Toggle the class on "main-nav"
        $target.classList.toggle('hidden');

      });
    });
  }

});

Store this snippet in js/nav.js and simply require('./nav') in your main js/app.js

Here's a demo to illustrate the result (resize the output tab)


Share:
Like:

Disable AdBlock on this domain and offer me a cup of coffee :)