The color of active links in TailwindCSS remains unchanged

In my project, I am using NextJS along with Tailwind CSS to create a top navigation bar. My goal is to change the text color for active links within the navigation bar. Below is the code snippet I have implemented:

const Header = () => {
    return(
        <header>
            <nav className="sd:max-w-6xl mx-auto">
                <ul className="flex py-2">
                    <li className="mr-auto ml-4">
                        <Link href="/"><a><Image width={80} height={80} src="/images/brand-logo.png" alt="ECT Logo"/></a></Link>
                    </li>
                    <li className="mr-4 my-auto hover:text-indigo-600 font-normal font-serif text-brand-darkblue text-xl active:text-indigo-600">
                        <Link href="/"><a>Home</a></Link>
                    </li>
                    <li className="mr-4 my-auto hover:text-indigo-600 font-normal font-serif text-brand-darkblue text-xl active:text-indigo-600">
                        <Link href="/user/signup"><a>Join</a></Link>
                    </li>
                    <li className="mr-4 my-auto hover:text-indigo-600 font-normal font-serif text-brand-darkblue text-xl active:text-indigo-600">
                        <Link href="/user/login"><a>Login</a></Link>
                    </li> 
                </ul>
        </nav>
        </header>
    )

}

In addition to the code snippet above, I have made modifications in my tailwind.config.css file as follows:

module.exports = {
  #
  variants: {
    extend: {
      textColor: ['active'],
    },
 
}

Despite implementing these changes, the text color does not change for active links as expected. I would appreciate any guidance on what I might be doing wrong in this setup.

Answer №1

There appears to be a confusion between two concepts:

  1. The active state in Tailwind CSS, which pertains to the state of an element while it is being pressed (https://tailwindcss.com/docs/hover-focus-and-other-states#active).
  2. The "active" page, indicating that the current page's path matches the nav item's href.

You cannot achieve concept 2 with concept 1 as they are different entities.

To differentiate and show the current page (concept 2), you must compare the current path with the <Link> element's path and implement conditional Tailwind classes accordingly.

For Next.js Pages Router:

import Link from 'next/link';
import { useRouter } from 'next/router';

export const Header = () => {
  const router = useRouter();

  return (
    <header>
      <Link href="/">
        <a className={router.pathname === "/" ? "active" : ""}>
           Home
        </a>
      </Link>
    </header>
  )
}

Source: https://dev.to/yuridevat/how-to-add-styling-to-an-active-link-in-nextjs-593e

For Next.js App Router (Update March 2024):

'use client';
 
import { usePathname } from 'next/navigation';
 
export const Header = () => {
  const pathname = usePathname();

  return (
    <header>
      <Link href="/">
        <a className={pathname === "/" ? "active" : ""}>
           Home
        </a>
      </Link>
    </header>
  );
};

This is a sample approach:

import { usePathname } from "next/navigation";

const NAV_ITEMS = [
  { href: "/", label: "Home" },
  { href: "/about", label: "About" },
];

export const Nav = () => {
  const pathname = usePathname();

  return (
    <nav>
      {NAV_ITEMS.map(({ href, label }) => {
        const isActive = pathname === href;

        return (
          <Link
            key={href}
            href={href}
            className={`${isActive ? "text-blue-500" : "text-black"} text-sm`}
          >
            {label}
          </Link>
        );
      })}
    </nav>
  );
};

By using a helper library like classnames, the code can be streamlined:

<Link
  key={href}
  href={href}
  className={classnames("text-sm", {
    "text-blue-500": isActive,
    "text-black": !isActive,
  })}
>
  {label}
</Link>;;

Applying this methodology to your code, you could modify the className as follows:

<Link href="/user/signup">
    <a className={`mr-4 my-auto hover:text-indigo-600 font-normal font-serif text-xl ${router.pathname === "/user/signup" ? "text-indigo-600" : "text-brand-darkblue"}`}>
        Home
    </a>
</Link>

Answer №2

When you utilize NavLink, it automatically adds the active class to the link, however, it does not apply the active state in tailwindcss.

An effective solution is to create a custom variant like the following:

<NavLink to={``} className={'[&.active]:text-indigo-500}>
</NavLink>

This approach leverages the power of tailwindcss with pure CSS, while also preventing unnecessary use of state to avoid potential rendering issues.

Answer №3

To ensure the current URL is matched correctly, it is recommended to utilize NavLink instead of Link. Below is an example I have implemented:

<NavLink to={`/${link.name}`}  className={ ({isActive})=>  (" capitalize my-2 flex flex-col ") + (isActive?ActiveLink:NormalLink) }>
              {link.name}
  </NavLink>

Answer №4

Implementing dark/light mode toggle with NextJs and Tailwind: My Solution

    //CustomActiveLink.js
        import { useRouter } from 'next/router';
        import Link from 'next/link';
        import PropTypes from 'prop-types';
        import { useTheme } from 'next-themes';
        
        
        const CustomActiveLink = ({ href, children, ...rest }) => {
            const router = useRouter();
            const { theme, systemTheme } = useTheme();
            const useLoaded = () => {
               const [loaded, setLoaded] = useState(false);
               useEffect(() => setLoaded(true), []);
               return loaded;
            };
            const mounted = useLoaded();
        
            const isActive = router.asPath === href;
    const currentTheme =
            mounted && theme !== undefined && theme === 'system' ? systemTheme : theme;
        
            const activeLinkBgColor =
                currentTheme === 'dark'
                    ? 'bg-gray-700 text-white'
                    : 'bg-blue-600 text-white';
        
            const themeBgHover =
                currentTheme === 'dark'
                    ? 'hover:bg-gray-700 hover:text-white'
                    : 'hover:bg-blue-600 hover:text-white ';
        
            const activeLinkAndNotActiveColor = isActive
                ? activeLinkBgColor
                : `text-gray-300 ${themeBgHover}`;
        
            const className = `${activeLinkAndNotActiveColor} px-3 py-2 rounded-md text-sm font-medium`;
        
            return (
                <Link href={href} passHref {...rest}>
                    <a className={className} aria-current={isActive ? 'page' : undefined}>
                        {children}
                    </a>
                </Link>
            );
        };
        
        CustomActiveLink.propTypes = {
            href: PropTypes.string.isRequired,
        };   
        
        
        export default CustomActiveLink;

// Example of usage
 <CustomActiveLink href='/about'> About </CustomActiveLink>

Check out the results here: https://i.sstatic.net/XO6eo.jpg https://i.sstatic.net/3rW7E.jpg

Best of luck.

Answer №5

To rid yourself of this issue once and for all, it's essential to expand the Tailwind modifier.

  1. Begin by importing tailwindcss/plugin.
  2. Next, extend the standard modifier via the plugin.
  3. Implement the use of active:text-purple-500.
// tailwind.config.js
const plugin = require('tailwindcss/plugin');

module.exports = {
  // ...
  plugins: [
      // ... some plugins,
      plugin(function({ addVariant }) {
        addVariant('active', ['&:active', '&.router-link-active'])
      })
  ],
}
<template>
  <NuxtLink
    class="active:text-purple-500"
  >
    <slot></slot>
  </NuxtLink>
</template>

This method offers several advantages:

  1. Avoid errors when expanding the codebase, as you no longer need to worry about customizing the active state.
  2. Facilitate the migration of components between projects.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountered an error while running npm run dev on a NextJS application due to an

Upon running the npm run dev command, the next app is displaying an error message: $→mmoLD;%g?wŷ↓▬ovH0a5*ؒl͛Siy☺rO7%L]%∟hk ^ SyntaxError: Invalid or unexpected token at wrapSafe (internal/modules/cjs/loader.js:988:16) at Module._comp ...

Tips for running a dry default with Angular CLI

Query: Can dry-run be set as the default in a configuration? Purpose: Enabling dry-run by default simplifies the learning process by minimizing clean-up tasks if the command is not correct. This can encourage users to always perform a test run before exec ...

Using Angular 7 shared service to allow sibling components to exchange data between each other

In my Angular 7 application, I have two sibling components - a configurator component and a custom stepper component. The configurator component is responsible for fetching data from the API and performing calculations on it. I would like to display the ca ...

Looping Feature in Ionic Framework's Slides Component

Currently, I am working on developing an application using Ionic-Angular. When it comes to incorporating slides in my app, I opted for the ionic 4 ion-slides component. Everything was going smoothly until I wanted to enable looping for the slides so that u ...

Utilize HTTPS and HTTP with Express framework in node.js

Currently, I am utilizing the express (3.0) framework on node.js to handle routing in my application. While most of the application makes use of the http protocol, there is a specific route that I intend to serve exclusively via https. This particular par ...

Tips on displaying a navbar only when the user starts scrolling

I recently put together a navbar component using react/next.js, and I am looking to make it appear only when the user starts scrolling. If anyone has any insights or suggestions on how to achieve this, I would be really thankful! Below is the code snippe ...

Modifying the content within a DIV element

I want to make changes to my DIV. <div id="main"> <div id="one"> <div class="red"> ... </div> <img class="avatar" src="img/avatar1.jpg"/> <span class="name"> John < ...

Efficiently transmitting WebSockets events/messages to multiple controllers in AngularJS

Incorporating AngularJs, I created a factory to manage a WebSocket connection effectively. Here is the code: .factory('WebSocketConnection', function () { var service = {}; service.callbacks = []; service.connect = func ...

Tips for showcasing JSON data within an array of objects

I'm trying to work with a JSON file that has the following data: {"name": "Mohamed"} In my JavaScript file, I want to read the value from an array structured like this: [{value: "name"}] Any suggestions on how I can acc ...

Trouble accessing Strapi CMS data on Next.js frontend using React.js

Currently, I am in the process of developing a website using Strapi as the CMS and Next.js(React) for the Frontend. The website features an image slider that includes an image, a headline, and a description. I am trying to retrieve these elements from my S ...

Utilizing the "return" keyword in Javascript outside of function declarations

Exploring the Impact of Using the Return Keyword in JavaScript Scripts Beyond Functions in Browsers and Node.js Recently, I experimented with utilizing the return keyword in a Node.js script like so: #!/usr/bin/env node return 10; My initial assumption ...

Display information using an ASP.Net barcode scanner

Currently, I am developing a WCF service application that involves receiving characters from a barcode reader and displaying the data on the UI for the user. My issue arises when inputting data using the keyboard into a textbox; everything functions corr ...

Adding a JSON file to an Angular app hosted on a Grunt server

I'm currently following a beginner's guide for Angular and I need to incorporate a JSON file into my project. I started off by using Yeoman to set up my application, which is running on grunt. var phonecatApp = angular.module('phonecatApp& ...

Bootstrap navigation bar collapsing horizontally instead of vertically

My Navbar is collapsing correctly, but when I click the toggle icon after it's collapsed, the items appear in a horizontal row instead of the intended vertical block. I have checked the code on the Bootstrap 5 example page and tried to replicate it, b ...

How can I adjust the Bootstrap container width without it changing when resizing the browser window?

As I work on developing my website, I am utilizing Twitter's bootstrap grid system. Despite my efforts, I have been unable to find a solution for fixing the width of the site. My goal is to lock the size in place so that it remains constant regardless ...

From Ruby to Javascript: Solving the Challenges of Date Calculation

Can you help me convert this Ruby snippet into JavaScript? I can't seem to get the expected output. Here is the original Ruby code: require 'date' moment = DateTime.new(2014, 9, 27, 0, 0, 0, DateTime.now.offset) intervals = [['day&apo ...

What could be causing my media query to not function properly?

I've been experimenting with some basic media queries but am encountering an issue with the div element that has the class "container." Whenever I adjust the screen size to be between 992px and 1200px, the div disappears from the page. It's perpl ...

What is the best way to position an image in the center over a video using HTML and CSS?

I am currently developing a website with a background video and I want to overlay a company logo on top of it while keeping it centered. My coding language of choice for this project is using HTML and CSS. Here's the HTML code snippet I have for this ...

Function is raising an error with the wrong value or text

I am currently testing a form that I am in the process of developing. My goal is to have different values returned each time I click on a different item from the dropdown menu. If this explanation isn't clear, please take a quick look at my pen for cl ...

HTML form not compatible with POST method in MVC

Why doesn't the $.post() method work in this case? I have tried pressing the button but it doesn't seem to post to EditClassLessonHour. This is the corresponding View Code: <div class="jumbotron"> <form id="editClassLessonHour"> ...