How to Add Active Link Styles with Nextjs
Tags: nextjs, react, tutorial, webdev
Published: 2021-12-14 01:21:35

As a frontend developer, I love to make things that are a delight to the user. Subtle little details that make the page pop or give the webpage personality, things that make other developers go "nice".

So, I knew for my blog I wanted to have some active link styling on my navigation bar. The styling would not only give the page some character but would also improve the user experience.

My blog is built using Nextjs and styled-component at the time of writing this. Which meant that it wasnt as simple as using the [pseudo-class](https://www.peterlunch.com/blog/css-pseudo-elements) [:active](https://www.peterlunch.com/snippets/remove-underline-from-link) and applying styles to it when the link was in the `:active` state.

The reason it wasn't straightforward is the Nextjs `<Link>` component doesn't know what the current route is, so it can never hold an active state.

We can use the `next/router` to solve this problem and that is how I made the links below.

![svg animation styles of links on my blog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/13gvkmm5lhm8a3u5ok3k.gif)

If you want to see how you give you links in Nextjs active styles then read on.

## Creating Active Links with Nextjs

Unfortunately, you cannot use the `<Link>` component from Nextjs by itself to add active styling. Therefore, you need to use the `useRouter` hook which is part of the `next/router` component. The `useRouter` hook allows magically lets you access the `router` object inside any component. This is how we are going to tell our application which page (route) the user is on, so we can then tell the link to apply active styles.

The best solution in my opinion is to create a custom `<ActiveLink>` component, link the one below:

```jsx
import { useRouter } from "next/router";
import styled from "styled-components";

const StyledLink = styled.a`
  color: ${({ href, path }) => (href === path ? "red" : "black"};
`;

function ActiveLink({ children, href }) {
  const router = useRouter();

  const handleClick = (e) => {
    e.preventDefault();
    router.push(href);
  };

  return (
    <StyledLink href={href} onClick={handleClick} currentPath={router.asPath}>
      {children}
    </StyledLink>
  );
}

export default ActiveLink;
```

I like this solution for a few reasons, so let's go through it step by step.

The first thing is we don't lose the benefits that come from the `<Link>` component because we use the `push` method. This method handles the client-side transitions, meaning it is faster and doesn't trigger a full refresh. Which results in better performance and experience for the user. It also improves those tasty lighthouse scores.

Next, we use the `asPath` method. This method returns the path (or route) as shown in the browser address bar meaning we can conditionally check this against the href we pass as an argument to the `<ActiveLink>` component.

The result is it prevents us from needing to hardcode the paths on a parent element and we can handle the active state at the link level. This allows you to use the `ActiveLink` component in other components when every you want to apply `:active` styling.

To actually apply the active link styles, we pass the `StyledLink` two key props. The first is the `href`, the actual link we want next to route to. The second is `currentPath`, which is the route that is currently in the browser.

Now, using styled-components we can check if the `href` and the `currentPath` components match using a ternary. If they match we apply the active styles in this case `red` font otherwise we apply `black` font.

Now you can detect if a link is active using Nextjs, you can start making your links delight users. If you're interested in how I made the links in my blog, sign up to my [newsletter](https://www.peterlunch.com/newsletter) to be one of the first to get access to my article on SVG styling.

If you're set on using the `<Link>` component [Flavio has some solutions here](https://flaviocopes.com/nextjs-active-link/).