Creating Reusable Navigation Bar with Next.js and Tailwindcss

Creating Reusable Navigation Bar with Next.js and Tailwindcss

Introduction

Hello there 😃!! I recently took up Next.js to build a data-drive project due to its advantages over using plain React.js. I decided to challenge myself by using Tailwindcss for styling as well. Part of the earliest tasks I dealt with was creating a navbar that I could use on different pages and customize to have different links on it. I decided to share that with you in this tutorial. I will also show you how to create and clone a Github repository.

You can find the complete code here.

Prerequisites

You don't have to be fully conversant with the following as I shall be trying my best to explain a lot of the concepts at a beginner level. It would, however, help if you were familiar with the following:

  • Javascript
  • React.js
  • Tailwindcss
  • React components
  • React Props
  • JSX
  • ES6 Syntax

Also, have git installed on your computer. When I say "directory" I refer to folders.

Table of Contents

The tutorial will be structured as follows:

  1. Git repository setup
  2. Project directory setup
  3. Installation of Next.js
  4. Installation and configuration of Tailwindcss
  5. Strategy to create responsive and reusable navbar
  6. Creation of navbar component
  7. Styling of navbar component

1. Git Repository Setup

First navigate to github.com Image of link to github.com

Then create a new repository by clicking on this button: Create a new repository

Enter the name of the repository and give it a description then click on the button to create it. Create repository

Copy this link (you are about to use it to clone the repository locally). Git clone link

2. Project Directory Setup

Open your preferred terminal or command-line application in the directory where you want your project to be and type in this command.

git clone <link-that-you-copied>

Congratulations! You have successfully cloned a repository. The reason we first created the repository on Github then cloned it was so that we would not have to manually set a remote origin. The remote origin refers to the online platform that you use to store your code remotely. This provides redundancy as you would not lose your work if anything happened to the device you are coding on.

Afterwards navigate to the new directory by typing:

cd nextjs-navbar-tutorial[Text](Link)

3. Installation of Next.js

First, I'd like to go a little bit into what Next.js is. Next.js is React.js framework with advantageous features like:

  • Built-in image optimization
  • Production optimization
  • Built-in domain and subdomain routing
  • Optimized bundle-splitting

You can find out more at nextjs.org. To initialize your next.js application run the following command:

npx create-next-app@latest .

The "." refers to the current directory that you are in. Running this command will create and initialize a Next.js app. After creating the application, run the following command to start the server:

npm run dev

This will start the server on port :3000. Navigating to this link should display the following:

Default Next.js page With that, we successfully created our Next.js application! Next (pun intended) we install and set up Tailwindcss.

4. Installation and configuration of Tailwindcss

According to the official website, Tailwindcss is a composable, utility-first CSS framework. This means that it can be configured and used to build any design.

Tailwind CSS also has advantageous features like:

  • Being very useful for mobile screen-size development since it uses a mobile-first approach by default.
  • Enabling faster CSS styling since developers have to write relatively less CSS.
  • A common utility classes pattern.
  • Being highly customizable.

First we will install the Tailwindcss and its dependencies Shut down the running Next.js server to get access to use your terminal again by pressing ctrl + c Then run:

npm install -D tailwindcss postcss autoprefixer

Postcss is a tool that enables us to change our CSS using plugins written in JavaScript. In this case we use the autoprefixer plugin to add vendor-prefixes to our CSS. This solves the problem of certain styles not working in all browsers and makes our navbar compatible with all browsers.

Next we initialize Tailwindcss using the following command:

npx tailwindcss init -p

This will create tailwind.config.js and postcss.config.js. These two files allow us to configure Tailwindcss to fit our specific needs.

Replace the contents of tailwindcss.js.config with the following code:

module.exports = {
    content: [
        './pages/**/*.{js,ts,jsx,tsx}',
        './components/**/*.{js,ts,jsx,tsx}',
    ],
    theme: {
        extend: {},
    },
    plugins: [],
};

After that, open the globals.css file in your styles directory. Add the following lines of code at the top of the file:

@tailwind base;
@tailwind components;
@tailwind utilities;

With that we're ready to get started building 🥳🥳🥳🥳🥳🥳. Start your server again with the following command:

npm run dev

5. Strategy to create responsive and reusable navbar

One important aspect of software engineering is forming a plan before writing any code.

If you fail to plan you plan to fail. ~ Benjamin Franklin

Software engineers first solve the problem, then they write the code. That is why this step is essential. Here we plan how we'll go about building the navbar. The steps we'll follow are:

  • Creating the component directory
  • Creating Logo.js
  • Creating Navbar.js
  • Importing the relevant components (Logo and Link from Next.js)
  • Importing Navbar in index.js so that we can actively view our changes
  • Writing the markup code
    • Container
    • Logo, reusable links and menu-icon
    • Mobile view of reusable links
  • Styling the markup

6. Creation of navbar component

Create a directory called components in the root directory of your project

Create a directory called components

Create two files: Logo.js and Navbar.js

Create Logo.js and Navbar.js

Inside Logo.js write the following code:

import Link from 'next/link';

const Logo = () => {
    return (
        <Link href='/'>
            <a>LOGO</a>
        </Link>
    );
};

export default Logo;

The Link component from next/link allows navigation to other routes on the client-side. You can read more about it here. The href prop is the route that the link redirects to.

We create and export the function Logo. We export it to make it available in other files, this allows us to reuse this component wherever we want in our application. In the function we return the Link component with a HTML anchor tag inside.

The reason we have an anchor tag inside the Link is because you can't directly style the Link component. Instead we will style the anchor tag.

Write the following code in the Navbar.js file:

import Link from 'next/link';
import Logo from './Logo';

const Navbar = ({ link1, link2, link3, link1To, link2To, link3To }) => {
    return (
        <div>
            <nav>
                <Logo />
                <div>
                    <Link href={link1To}>
                        <a>{link1}</a>
                    </Link>
                    <Link href={link2To}>
                        <a>{link2}</a>
                    </Link>
                    <Link href={link3To}>
                        <a>{link3}</a>
                    </Link>
                </div>
                <button>
                    <svg
                        xmlns='http://www.w3.org/2000/svg'
                        className='h-6 w-6'
                        fill='none'
                        viewBox='0 0 24 24'
                        stroke='currentColor'
                        strokeWidth={2}
                    >
                        <path
                            strokeLinecap='round'
                            strokeLinejoin='round'
                            d='M4 6h16M4 12h16m-7 6h7'
                        />
                    </svg>
                </button>
            </nav>
            <div>
                <Link href={link1To}>
                    <a>{link1}</a>
                </Link>
                <Link href={link2To}>
                    <a>{link2}</a>
                </Link>
                <Link href={link3To}>
                    <a>{link3}</a>
                </Link>
            </div>
        </div>
    );
};

export default Navbar;

First we import two components, our logo and the Link component we discussed earlier. Then we create a div that will act as our container.

Inside the container we have the logo, a section for our links and a button that will only appear on mobile viewport. I got the icon for the button from this website. Clicking this button will reveal the links on a mobile menu (our navbar will be responsive).

You'll notice that we have curly braces inside our function parenthesis, Link href and anchor tags. In the parenthesis we destructure those values from our component props. You can read about destructuring here and about React.js props here.

Props are an integral feature of React. They make it possible to pass data between components which makes our lives easier. Props let us determine what the links say and where they point to when we import our navbar. Having the navbar as a component also allows us to use it wherever we want. Finally, we clear up the index.js file and import our navbar:

import Head from 'next/head';
import Navbar from '../components/Navbar';
import styles from '../styles/Home.module.css';

export default function Home() {
    return (
        <div className={styles.container}>
            <Head>
                <title>Next.js Navbar Tutorial</title>
                <meta name='description' content='Generated by create next app' />
                <link rel='icon' href='/favicon.ico' />
            </Head>

            <Navbar
                link1='About Us'
                link1To='/about'
                link2='Contact Us'
                link2To='/contact'
                link3='Subscribe'
                link3To='/subscribe'
            />

            <main className={styles.main}>
                <h1 className={styles.title}>
                    This is where the rest of your landing page content will go!
                </h1>
            </main>
        </div>
    );
}

Notice in the Navbar that we've given values to the attributes that we destructured when we defined the component. That is how we pass data through props. Your index page on the / route should look like this now:

Should look like this now

We're now ready to style our navbar.

7. Styling of navbar component

In the logo component add this className to the anchor tag:

className='font-bold text-xl tracking-wide hover:tracking-widest transform-all ease-in-out duration-700'

This will create a nice subtle hover effect everytime the mouse cursor hovers over the logo. It also increases the size of the font, makes the font bold and increases the letter spacing. Your Logo.js file should look like this now

import Link from 'next/link';

const Logo = () => {
    return (
        <Link href='/'>
            <a className='font-bold text-xl tracking-wide hover:tracking-widest transform-all ease-in-out duration-700'>
                LOGO
            </a>
        </Link>
    );
};

export default Logo;

The bulk of the work will now be in Navbar.js. Add this className to the top=level div:

className='py-5 flex items-center justify-between space-y-9 bg-black px-8 mx-auto text-slate-200'

First we set the layout of the navbar using flexbox. We center the contents of the navbar vertically and spacing out the components automatically. These classes also set the background color of the navbar to black, add a padding of 32px or 2rem to the left and right of the navbar, set the left and right margin of the navbar to auto and set the color of all the text in the navbar.

Then, add the following className to the nav tag.

className='flex items-center justify-between'

This arranges the logo, the link section and the menu-button on a straight line with the mobile nav links under them.

Next, add the following className to the div containing the links:

className='hidden md:flex items-center space-x-9'

Remember that tailwind is mobile-first oriented. The link section will be hidden on mobile and on any screen bigger than 768px the links will be centered and spaced out.

Add the following className to the button tag:

className='md:hidden flex items-center'

This will hide the button on any screen bigger than 768px. The button will only appear on mobile viewports.

Finally, we style the links for the mobile menu. Add the following className to the second div with Links inside:

className='mobile-menu hidden md:hidden flex flex-col items-end space-y-2 px-9 pt-3 pb-3 text-sm'

Now we add the toggle functionality to menu button to make the links appear and hide on click. We will write the following onClick function:

() => {
  document.querySelector('.mobile-menu').classList.toggle('hidden');
}

We use the JavaScript DOM manipulation to select the mobile-menu link section then toggle the "hidden" class from its list of classes. To implement it we add a function assigned to an onClick prop to the button this way:

<button 
    onClick={() => {
        document.querySelector('.mobile-menu').classList.toggle('hidden');
    }}
>
--menu icon--
</button>

With that the navbar is complete. Your page should look like this now:

Desktop view

Mobile view with menu closed

Mobile view with menu open

The code in Navbar.js should look like this:

import Link from 'next/link';
import Logo from './Logo';

const Navbar = ({ link1, link2, link3, link1To, link2To, link3To }) => {
    return (
        <div className='py-5 flex flex-col items-between space-y-9 bg-black px-8 mx-auto text-slate-200'>
            <nav className='flex items-center justify-between'>
                <Logo />
                <div className='hidden md:flex items-center space-x-9'>
                    <Link href={link1To}>
                        <a>{link1}</a>
                    </Link>
                    <Link href={link2To}>
                        <a>{link2}</a>
                    </Link>
                    <Link href={link3To}>
                        <a>{link3}</a>
                    </Link>
                </div>
                <button
                    onClick={() => {
                        document.querySelector('.mobile-menu').classList.toggle('hidden');
                    }}
                    className='md:hidden flex items-center'
                >
                    <svg
                        xmlns='http://www.w3.org/2000/svg'
                        className='h-6 w-6'
                        fill='none'
                        viewBox='0 0 24 24'
                        stroke='currentColor'
                        strokeWidth={2}
                    >
                        <path
                            strokeLinecap='round'
                            strokeLinejoin='round'
                            d='M4 6h16M4 12h16m-7 6h7'
                        />
                    </svg>
                </button>
            </nav>
            <div className='mobile-menu hidden md:hidden flex flex-col items-end space-y-2 px-9 pt-3 pb-3 text-sm'>
                <Link href={link1To}>
                    <a>{link1}</a>
                </Link>
                <Link href={link2To}>
                    <a>{link2}</a>
                </Link>
                <Link href={link3To}>
                    <a>{link3}</a>
                </Link>
            </div>
        </div>
    );
};

export default Navbar;

You can find the complete code here.

Conclusion

Thank you so much for going through this. I hope it was of help to you. Please feel free to contact me if you have any questions or if you need help customizing it.

About the author

Andrew Mukare is a fullstack software engineer (Frontend heavy) who also dabbles in UI/UX design. You can contact him on Twitter or LinkedIn. You can see his projects on his github.