Next.js

Highlighting the active link in Next.js nested routes

Screenshot of a link with active style

While building this site I noticed the "Blog" link in the navigation wasn't highlighting when viewing a blog post.

To build the navigation I'm using an array of `navLinks` in my config file.

1export const config = { 2 ... 3 navLinks: [ 4 { 5 text: 'Blog', 6 url: '/blog', 7 external: false, 8 }, 9 { 10 text: 'Github', 11 url: 'https://github.com/AidanZealley', 12 external: true, 13 } 14 ], 15 ... 16}

The `pathname` field from `useRouter` wasn't matching the `/blog` url in my config file while on a url like `/blog/my-blog-post`.

I wrote a function to compare only the first part of the `pathname` against the url in the config.

1const isSameSiteSection = (path, configUrl) => `/${path.split('/')[1]}` === configUrl

Now I use the value of that function to conditionally add the active link class.

Full Nav component

1import Link from 'next/link' 2import { useRouter } from 'next/router' 3import OpenInNewRoundedIcon from '@material-ui/icons/OpenInNewRounded' 4import { config } from '@utils/config' 5import styles from './styles.module.css' 6 7export const Nav = () => { 8 const { navLinks } = config 9 const isSameSiteSection = (path, configUrl) => `/${path.split('/')[1]}` === configUrl 10 const { pathname } = useRouter() 11 return ( 12 <nav className={`${styles.nav}`}> 13 {navLinks.map(({ label, url, external }, index) => ( 14 <Link key={index} href={url}> 15 <a 16 className={` 17 ${styles.link} 18 ${isSameSiteSection(pathname, url) ? ` ${styles.active}` : ''} 19 `} 20 target={external ? '_blank' : ''} 21 > 22 {label} 23 { 24 external 25 ? <OpenInNewRoundedIcon fontSize="small"/> 26 : '' 27 } 28 </a> 29 </Link> 30 ))} 31 </nav> 32 ) 33}