Having a web application without the appropriate styling of active links can be a nightmare for users. In this article, we see how to easily style active links in NextJS
Today, we’re be taking a look at how to style active links in NextJS. There’s no worse feeling as a user than having no visual clue to know where you currently are on a webpage. If this was a React app, we could utilise the React Router’s NavLinkcomponent, using the activeclass to style whichever links are active.
But this is a NextJS app, and we’re certainly not using React Router as Next has it’s own routing. So let’s begin: I’ll be using Tailwind CSS for this example, but you’re free to use whatever you’re comfortable with. Let’s install NextJS alongside TailwindCSS.
npx create-next-app@latest active-links --typescript --eslint
cd active-links
npm install -D tailwindcss postcss autoprefixer
Set up your tailwind.config.ts as needed, if you’re not using Tailwind, please kindly skip this step. Also, adjust your globals.css according to your preference.
import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
backgroundImage: {},
container: {
center: true,
padding: {
DEFAULT: "1rem",
sm: "2rem",
lg: "4rem",
xl: "5rem",
},
},
},
},
plugins: [],
};
export default config;
Next, we’re going to create a simple navbar with 3 links: Page One, Page Two and Page Three. For this, I usually create a Components folder and create a new file titled Navbar.tsx. Once you’ve created this file, please remember to import it into the layout.tsx file so it can be rendered across all pages.
// layout.tsx
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
import Navbar from './components/Navbar'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Active Link Test',
description: 'Easily style active links in NextJS!',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>
<Navbar />
{children}</body>
</html>
)
}
Your file structure should look similar to this
// Navbar.tsx
"use client";
import React from 'react'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
const Navbar = () => {
const currentPath = usePathname();
return (
<nav className='w-full h-fit mx-auto border-b '>
<div className="container flex justify-between h-[14vh] items-center">
<div className="logo">
<Link href={'/'}><h4 className='text-2xl tracking-tight font-bold'>active <span className=' text-green-500 uppercase'>Linktest</span></h4></Link>
</div>
<div className="links flex gap-10 text-slate-600">
<Link href={'/page-one'} className={currentPath === "/page-one" ? "text-green-500 font-semibold" : "text-slate-600"}>Page One</Link>
<Link href={'/page-two'} className={currentPath === "/page-two" ? "text-green-500 font-semibold" : "text-slate-600"}>Page Two</Link>
<Link href={'/page-three'} className={currentPath === "/page-three" ? "text-green-500 font-semibold" : "text-slate-600"}>Page Three</Link>
</div>
</div>
</nav>
)
}
export default Navbar
In the code snippet above, we’ve created a simple navbar component with 3 pages. To create a page via the app router, create a folder with the desired pathname, e.g, mine is pages-one. Then create a page.tsx inside the folder and customise accordingly. Here’s mine:
In order to know the current path, we’re using the usePathname hook from next/navigation, and since this is a Client Component, we need to declare use client at the top of our file . We have a variable called currentPath which stores the value returned by the usePathname hook.
We’ve also added a simple logic that checks if our current path matches the path name. For example, if currentPath === "/page-one" then we style the link accordingly. In this case, the styling is text-green-500 font-semibold which is Tailwind for a shade of green and semibold font weight.
Now, let’s add some content to each page. For simplicity sake, I made the contents the same for all 3 pages. So copy and modify accordingly. I’ll use page one as an example:
// page one
// page.tsx
import React from 'react'
const PageOne: React.FC = () => {
return (
<section className='container mt-14 rounded-3xl py-10 '>
<div className=''>
<h2 className='text-3xl font-semibold lg:text-4xl '>Page One</h2>
<div className='py-6'>
<p className='text-green-600 max-w-3xl text-xl py-4'>Praesent elementum facilisis leo vel fringilla est ullamcorper eget nulla. Etiam dignissim diam quis enim lobortis. Neque viverra justo nec ultrices. Dui vivamus arcu felis bibendum ut tristique et egestas. Dolor sit amet consectetur adipiscing elit. Purus viverra accumsan in nisl nisi scelerisque.</p>
<p className="text-slate-500 max-w-3xl py-4">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar neque laoreet suspendisse interdum consectetur libero id faucibus. Facilisis mauris sit amet massa vitae tortor condimentum lacinia quis. Id velit ut tortor pretium viverra. Orci dapibus ultrices in iaculis nunc sed. In iaculis nunc sed augue lacus viverra vitae.</p>
<p className="text-slate-500 max-w-3xl py-4">Tellus integer feugiat scelerisque varius morbi enim. Bibendum at varius vel pharetra vel turpis nunc. Ultrices mi tempus imperdiet nulla malesuada pellentesque..</p>
</div>
</div>
</section>
)
}
export default PageOne
active link now displaying in green text colour
Now, let’s make the menu responsive.
"use client";
import React, { useState } from 'react'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
import { BiMenuAltRight } from 'react-icons/bi'
import { AiOutlineClose } from 'react-icons/ai'
const Navbar = () => {
const currentPath = usePathname();
const [toggle, setToggle] = useState(false);
return (
<nav className='w-full h-fit mx-auto border-b bg-white'>
<div className="container flex justify-between h-[14vh] items-center">
<div className="logo">
<Link href={'/'}><h4 className='text-2xl tracking-tight font-bold'>active <span className=' text-green-500 uppercase'>Linktest</span></h4></Link>
</div>
<div className='text-3xl text-slate-600 cursor-pointer lg:hidden' onClick={() => setToggle(prev => !prev)}>
{toggle ? <BiMenuAltRight /> : <AiOutlineClose />}
</div>
<div className="hidden lg:flex links gap-10 text-slate-600">
<Link href={'/page-one'} className={currentPath === "/page-one" ? "text-green-500 font-semibold" : "text-slate-600"}>Page One</Link>
<Link href={'/page-two'} className={currentPath === "/page-two" ? "text-green-500 font-semibold" : "text-slate-600"}>Page Two</Link>
<Link href={'/page-three'} className={currentPath === "/page-three" ? "text-green-500 font-semibold" : "text-slate-600"}>Page Three</Link>
</div>
</div>
{!toggle && <div className='w-full lg:hidden'>
<div className='container flex flex-col gap-6 py-10'>
<Link href={'/page-one'} className={`${currentPath === "/page-one" ? "text-white font-semibold px-3 bg-green-500 rounded-md" : "text-slate-600"} py-3 text-center`}>Page One</Link>
<Link href={'/page-two'} className={`${currentPath === "/page-two" ? "text-white font-semibold px-3 bg-green-500 rounded-md" : "text-slate-600"} py-3 text-center`}>Page Two</Link>
<Link href={'/page-three'} className={`${currentPath === "/page-three" ? "text-white font-semibold px-3 bg-green-500 rounded-md" : "text-slate-600"} py-3 text-center`}>Page Three</Link>
</div>
</div>}
</nav>
)
}
export default Navbar
Two icons have been imported from React Icons, and we’re using a state variable toggle to monitor if the menu has been clicked. If so, it displays the menu for mobile. Let’s see how the mobile menu looks.
mobile menu showing active link
Now you have a navbar with styled active links! You can add different active styles that you prefer.
This is a quick and easy way to help a user when navigating your application. If you’re having troubles with images not displaying in NextJS , have a look at this article. For a reusable custom button component in Tailwind , please read this article.
Thanks a lot for reading, see you in the next one!
Top comments (0)