How to Build a Mobile-friendly, Fully Responsive Website Navigation Using Tailwind CSS
Tags: tailwindcss, mobile, css, html
Published: 2021-05-25 16:06:49

**Your website’s navigation is probably the single most important element on your page - you’ve got to make sure you get it right.**

Yes, writing captivating content for your website is important but this will all be in vain if your users can’t navigate to it.

What makes things even harder, is that you also have to consider the usability of your navigation on countless devices, screen sizes and resolutions.

Luckily for you, there are several techniques and best practices to follow that will help you master the UI and UX of your website’s navigation.

We’ll explore them in this article.

>Check out the [DEMO](https://nav.brandymedia.co.uk/)
Download the [SOURCE CODE](https://github.com/brandymedia/tailwind-responsive-navigation)

{% github brandymedia/tailwind-responsive-navigation no-readme %}

### So what are we building

We’re going to build a mobile-friendly, fully responsive navigation using Tailwind CSS that:

- Works across all screen sizes
- Uses ~~little to~~ no custom CSS
- Implements simple vanilla JavaScript
- Doesn’t repeat or duplicate elements
- Gives you a great starting point for your own projects

###The Code

I believe it would be beneficial from a learning perspective for you to read the rest of the tutorial. I also get that you may be busy and just need to implement the solution.

So here’s the completed code.

**index.html**
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Responsive Navigation</title>
    <link rel="stylesheet" href="public/dist/styles.css">
</head>
<body>
    <h1 class="text-center my-10 text-4xl">Responsive Navigation</h1>
    <nav class="flex flex-col md:flex-row bg-gray-200 p-5">
        <div class="flex flex-wrap justify-between items-center">
            <div>
                Logo goes here...
            </div>
            <div class="burger md:hidden">
                <div class="bar1 h-1 w-7 my-1.5 bg-gray-800 duration-300"></div>
                <div class="bar2 h-1 w-7 my-1.5 bg-gray-800"></div>
                <div class="bar3 h-1 w-7 my-1.5 bg-gray-800 duration-300"></div>
            </div>
        </div>
        <ul class="links md:flex flex-col md:flex-row text-center w-full md:justify-around hidden">
            <li>
                <a href="#" class="block p-5">
                    Home
                </a>
            </li>
            <li>
                <a href="#" class="block p-5">
                    Services
                </a>
            </li>
            <li>
                <a href="#" class="block p-5">
                    About
                </a>
            </li>
            <li>
                <a href="#" class="block p-5">
                    Contact
                </a>
            </li>
            <li>
                <a href="#" class="block p-5">
                    Blog
                </a>
            </li>
        </ul>
    </nav>
    <script src="public/dist/script.js"></script>
</body>
</html>
```
**script.js**
```javascript
const burger = document.querySelector('.burger');
const links = document.querySelector('.links');
const bar1 = document.querySelector('.bar1');
const bar2 = document.querySelector('.bar2');
const bar3 = document.querySelector('.bar3');

burger.addEventListener('click', () => {
	links.classList.toggle('hidden');
    bar1.classList.toggle('transform');
    bar1.classList.toggle('translate-y-1.5'); 
    bar1.classList.toggle('-rotate-45');
    bar2.classList.toggle('hidden');
    bar3.classList.toggle('transform');
    bar3.classList.toggle('-translate-y-1');        
    bar3.classList.toggle('rotate-45');
});
```

If you do have the time, then please read on...

###Initial setup

As I’m sure you’ve guessed, we’re going to be using the amazing Tailwind CSS framework for all of our CSS styling in this project.

You could just include a link to their CDN but then you’re not going to benefit from all of the fantastic features.

So let’s include TailwInd CSS via NPM.

`npm i tailwindcss@latest postcss@latest autoprefixer@latest postcss-cli`

Once this has finished installing, we need to set up a couple more things before we can code our navigation.

Open the package.json file, as we need to add a couple of scripts to allow us to compile our Tailwind CSS later.

```
"build": "postcss ./src/styles.css -o ./public/dist/styles.css",
"prod": "NODE_ENV=production postcss ./src/styles.css -o ./public/dist/styles.css"
```

In your terminal, run `npx tailwindcss init -p` to create our `tailwind.config.js` and `postcss.config.js` files, then open up the `tailwind.config.js` file and update `darkMode` to `class`.

Before we can compile our CSS, we need to create the source CSS file.

Create the src folder `mkdir src` then `cd src` in to the directory and create the CSS file `touch styles.css`.

Add the included to the styles.css file

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

Then run `npm run build`. This should output our compiled styles to our `public/dist/styles.css` file.

###HTML markup - the structure (& style)

Now we have included Tailwind CSS in our project and compiled the development bundle, it’s time to start writing the HTML markup.

If you’re already familiar with Tailwind CSS you’ll know that to style HTML elements, you add various ‘utility’ classes inline. This saves a lot of time writing custom CSS, speeding up development considerably.

First things first, let's get our 'boilerplate' set out.

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Responsive Navigation</title>
</head>
<body>
    
</body>
</html>
```

If you're using VS Code, you can automagically write the above code by hitting `!` then `tab`.

You'll then need to add a link to your compiled styles.css in your head tag.

```html
	...
	<link rel="stylesheet" href="public/dist/styles.css">
</head>
```

Next, within the body tag, let's add the HTML for the structure of the actual navigation.

```html
<nav>
    <ul class="links">
        <li>
            <a href="#">
                Home
            </a>
        </li>
        <li>
            <a href="#">
                Services
            </a>
        </li>
        <li>
            <a href="#">
                About
            </a>
        </li>
        <li>
            <a href="#">
                Contact
            </a>
        </li>
        <li>
            <a href="#">
                Blog
            </a>
        </li>
    </ul>
</nav>
```

The above code should be pretty self-explanatory but to recap - we create a `nav` tag and then inside we add an unordered list for our links, which is common convention for website navigations.

Next, let's use Tailwind's utility classes to add some styling as it's looking a little bit boring.

There are a few ways we could approach the layout of our navigation, in this case, we are going to use flexbox. This will give us all the tools we need to be able to respond to the various screen sizes we need to cater for.

Mobile web browsing overtook desktop web browsing several years ago, so it makes sense to build the navigation mobile-first. We'll concentrate on getting this to work on mobile (smaller screens) and then adapt this to work on desktops later.

Most mobile devices have limited horizontal real estate so it's common practice to arrange your navigation's links beneath one another in a vertical alignment. We will use Tailwind's flexbox utility classes to achieve this.

```html
<nav class="flex flex-col md:flex-row bg-gray-200 p-5">
	<ul class="links flex flex-col text-center">
		...
	</ul>
</nav>
```

What have we just done? We set the `ul` as flexbox with `flex` and then positioned the links in a column so they stack with `flex-col` then finally centred the text with `text-center`.

Because mobile devices don't have hover, it's really important each link has enough spacing so the user can easily press the desired option. Let's add some padding to each link to achieve this.

```html
<li>
	<a href="#" class="block p-5">
	  Home
  </a>
</li>
```

This is starting to look and work a lot better now. It's not ideal having the links taking up the entire vertical space of the screen though. We need a way to hide these when not in use.

To achieve this, we'll create a custom burger style button that will use some basic vanilla JavaScript to hide and show the links as they're required. Let's add the basic HTML structure.

```html
<div>
    <div>
        <div></div>
        <div></div>
        <div></div>
    </div>
</div>
<ul class="links flex flex-col text-center">
	...
</ul>
```

One of the goals whilst building this navigation, was to use ~~little to~~ no custom CSS if possible. With this in mind, we're now going to use more of Tailwind's CSS utility classes to build the custom burger menu icon.

```html
<div class="flex flex-wrap justify-between items-center">
    <div class="burger">
        <div class="h-1 w-7 my-1.5 bg-gray-800"></div>
        <div class="h-1 w-7 my-1.5 bg-gray-800"></div>
        <div class="h-1 w-7 my-1.5 bg-gray-800"></div>
    </div>
</div>
```

The navigation is now laid out in a sensible way for smaller devices such as mobiles. However, on desktop, the links are taking up too much of the space and would be better placed horizontally. Let's fix that now.

Also, the burger menu is not required on bigger screens, so we will hide that too.

Tailwind conveniently provides responsive utility modifiers classes that lets us target various screen sizes. In our example, we'll set the links to align next to each other horizontally with `flex-row` and hide the burger with the `hidden` class. Notice the `md:` modifier pre-fixed to the classes.

```html
	<div>    
		<div class="burger md:hidden">
        <div class="h-1 w-7 my-1.5 bg-gray-800"></div>
        <div class="h-1 w-7 my-1.5 bg-gray-800"></div>
        <div class="h-1 w-7 my-1.5 bg-gray-800"></div>
    </div>
</div>
<ul class="links md:flex flex-col md:flex-row text-center w-full md:justify-around">
```

Before we tackle the JavaScript to hide and show the links on mobile, I want to add a section where we can add our logo or site name. So let's update our HTML markup.

```html
<nav class="flex flex-col md:flex-row bg-gray-200 p-5">
    <div>
        <div>
            Logo goes here...
        </div>
        <div class="burger md:hidden">
            <div class="bar1 h-1 w-7 my-1.5 bg-gray-800"></div>
            <div class="bar2 h-1 w-7 my-1.5 bg-gray-800"></div>
            <div class="bar3 h-1 w-7 my-1.5 bg-gray-800"></div>
        </div>
    </div>
    <ul class="links md:flex flex-col md:flex-row text-center w-full md:justify-around hidden">
```

You'll notice the links have now disappeared on mobile, this is in preparation for our JavaScript. We'll write that now.

In the `public/dist` directory create a new file called `script.js` and link in your HTML file just before the closing body tag.

```html
	<script src="public/dist/script.js"></script>
</body>
```

Open the `script.js` file and add the following code.

```javascript
const burger = document.querySelector('.burger');
const links = document.querySelector('.links');

burger.addEventListener('click', () => {
	links.classList.toggle('hidden');
});
```

You should now have a fully functional mobile-friendly, responsive navigation.

To add the cherry on top, let's add an animation to the burger icon.

Update your HTML to...

```html
<div class="burger md:hidden">
    <div class="bar1 h-1 w-7 my-1.5 bg-gray-800 duration-300"></div>
    <div class="bar2 h-1 w-7 my-1.5 bg-gray-800"></div>
    <div class="bar3 h-1 w-7 my-1.5 bg-gray-800 duration-300"></div>
</div>
```

Then update your `script.js` file to...

```javascript
const burger = document.querySelector('.burger');
const links = document.querySelector('.links');
const bar1 = document.querySelector('.bar1');
const bar2 = document.querySelector('.bar2');
const bar3 = document.querySelector('.bar3');

burger.addEventListener('click', () => {
	links.classList.toggle('hidden');
    bar1.classList.toggle('transform');
    bar1.classList.toggle('translate-y-1.5'); 
    bar1.classList.toggle('-rotate-45');
    bar2.classList.toggle('hidden');
    bar3.classList.toggle('transform');
    bar3.classList.toggle('-translate-y-1');        
    bar3.classList.toggle('rotate-45');
});
```

That wraps up this tutorial.

If you enjoyed the tutorial, please make sure you follow me here on [dev.to](https://dev.to/brandymedia) and [Twitter](https://twitter.com/brandymedia) so you don’t miss out when new tutorials are available.