Tips on incorporating several class names into Next.js elements

My current challenge involves an unordered list element with the following structure:


     <ul className={styles["projects-pd-subdetails-list"]}>
        {detail.subdetails.map((sub) => (
          <li
             className={styles["projects-pd-text projects-pd-subdetail"]}
          >
            {sub}
          </li>
        ))}
     </ul>

In a standard React element, applying multiple classes to the li element is simple:

<li className="projects-pd-text projects-pd-subdetail">{sub}</li>

Unfortunately, due to spacing issues in Next.js, the styles are being ignored. How can I solve this problem and correctly handle two classNames for my li element?

Answer №1

Utilizing multiple className is possible by combining them like this

<li className={`${styles.projects-pd-text} ${styles.projects-pd-subdetail}`}>
   {sub}
</li>

However, a potential issue may arise. It could result in an error (though not confirmed). To avoid this, consider using camelCase for your CSS class names.

<li className={`${styles.projectsPdText} ${styles.projectsPdSubdetail}`}>
   {sub}
</li>

Alternatively, if you prefer not to use camelCase

<li className={`${styles["projects-pd-text"]} ${styles["projects-pd-subdetail"]}`}>
       {sub}
</li>

Feel free to inform me of the outcome.

Another convenient method of managing multiple classes is through the clsx library. The advantage of clsx is the ability to handle conditional class names as well.

// Strings (variadic)
clsx('foo', true && 'bar', 'baz');
//=> 'foo bar baz'

// Objects
clsx({ foo:true, bar:false, baz:isTrue() });
//=> 'foo baz'

// Objects (variadic)
clsx({ foo:true }, { bar:false }, null, { '--foobar':'hello' });
//=> 'foo --foobar'

// Arrays
clsx(['foo', 0, false, 'bar']);
//=> 'foo bar'

// Arrays (variadic)
clsx(['foo'], ['', 0, false, 'bar'], [['baz', [['hello'], 'there']]);
//=> 'foo bar baz hello there'

// Kitchen sink (with nesting)
clsx('foo', [1 && 'bar', { baz:false, bat:null }, ['hello', ['world']]], 'cya');
//=> 'foo bar hello world cya'

Answer №2

To easily combine elements in an array, a simple array join method can be used.

["apple", "banana", "orange"].join(" and ")

This will give us:

"apple and banana and orange"

<div className={[styles.fruit1, styles.fruit2, styles.fruit3].join(" ")}>
   Fruit Salad
</div>

Alternatively, the classes can be stored in a variable for future use:

const fruitClasses = [styles.fruit1, styles.fruit2]

// somewhere in the code
<div className={[...fruitClasses, styles.fruit3].join(" ")}>
   Another Fruit Salad
</div>

Answer №3

I have not had the opportunity to work with Next.js, as mentioned in my previous comment.

It seems like styles are organized in a key-value pair format, for example:

const styles = {
    "projects-pd-subdetails-list": "Class Name A",
    "projects-pd-text": "Class Name B",
    "projects-pd-subdetail": "Class Name C"
}

This indicates that when you use a line such as

styles["projects-pd-text projects-pd-subdetail"]
, you are trying to fetch the value for the key
"projects-pd-text projects-pd-subdetail"
, which is not present in the map.

My suggestion would be to retrieve the values separately from the map and then concatenate them using your preferred method of string manipulation.

className={styles["projects-pd-subdetail"] + " " + styles["projects-pd-text"]}

// OR

className={`${styles["projects-pd-subdetail"]} ${styles["projects-pd-text"]}`}

Answer №4

clsx is a popular utility for conditionally adding classes to an element.

Check out clsx on npm

Answer №5

The most efficient way to handle this is by utilizing the join() method, as previously pointed out by @rain in a discussion.

An alternative approach would be to implement universal css class names.

<span className={[styles.grid, "disabled"].join(" ")}>content</span>

Answer №6

With the release of Nextjs version 13.4+, you now have the option to utilize the default supported cn function, which leverages the power of clsx.


layout.tsx


import { cn } from "@/lib/utils";
export default function Component(){
   return <div className={cn("flex font-sans","inter.className","h-full")}/>
}

The lib/utils.ts file contains the following by default:

import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
 
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

Answer №7

If you're tired of constantly typing out styles.className for every class you want to add to an element, consider creating a utility function to streamline the process.

For instance, I crafted this function:

export const classes = (styles: any, classes: string) => {
    const list = classes.split(' ');

    classes = '';
    for (const className of list) {
        classes += `${styles[className] }`
    }
    return classes;
} 

and saved it in a util file.

Now, when working on elements, I can simply do this:

<div className={classes( styles, 'hero-container text-success text-bold italicize another-class yet-another-class ')}>
     Lorem ipsum dolor
</div>

A BONUS:

When starting with NextJS on VSCode, I struggled with emmet tag generation not displaying the classnames the way NextJS does when typing a css class selector.

    "Complete NextJS Classname Emmet": {
        "scope": "javascript,typescript,typescriptreact,javascriptreact",
        "prefix": ["."],
        "body": [
            "<div className={classes( styles, '$1')}>",
            "\t$2",
            "</div>"
        ],
        "description": "Lean autocomplete emmet in nextjs css modules classname"
    }

I added this snippet to my User Snippets in VSCode preferences for typescriptreact.json. These adjustments have certainly improved my experience working with classnames in NextJS, particularly on VSCode.

Answer №8

Success was achieved in my case.

<div className={styles.side +" "+ styles.side2}>side2</div>

Credit goes to CodeMaster

Answer №9

If you utilize console log for your css or scss module class (i.e., ImportedStyleModule.someClassName), you will notice that it is simply a string with an auto-generated UID added.

Therefore, since it is just a string, there are multiple ways to concatenate them together:

//ts         
const mergeStyles = (styleArray: string[]) => (styleArray.map((style: string) => `${style}`).join(" "));        
                        
//js
const mergeStyles = (styleArray) => (styleArray.map((style) => `${style}`).join(" "));
                        
//example
return (
    <span
        onClick={() => setIsClicked(!isClicked)}
        className={`${!!isClicked 
            ? mergeStyles([NavbarStyle.navButton, NavbarStyle.navButtonOpen])
            : NavbarStyle.navButton}`}
    >
        <Image src='/image-logo.svg' alt='logo' width='80px' height='40px' />
    </span>
);

Answer №10

 <div className={`${GloStyles.flexRow} ${MyStyles.gap_10rem}`}> Hello </div>

Here's the breakdown:

  • The className attribute only accepts a string.
  • By using String templates, we can easily combine multiple classes just like in a regular React app.

View image description here View image description here

Answer №11

Using a function would definitely make the code more organized and readable.

const updateClassName = (className) =>  className.split(' ').map(c => styles[c]).join(' ')

You can easily utilize this function in your JSX like this:

<div className={updateClassName("firstClass secondClass")}></div>

If you need to handle conditional class names, I recommend checking out classnames package on npm.

Answer №12

This is my unique approach to styling components

<ul>
<li className={router.pathname == "/" && styles.active}><Link href="/">Home</Link></li>
<li className={router.pathname == "/about" && styles.active}><Link href="/about">About</Link></li>
<li className={router.pathname == "/contact" && styles.active}><Link href="/contact">Contact</Link></li>
<li><Link href="/404">404</Link></li>
</ul>

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

What is the best way to determine the size of the URLs for images stored in an array using JavaScript?

I am working on a project where I need to surround an image with a specific sized 'div' based on the image's dimensions. The images that will be used are stored in an array and I need to extract the height and width of each image before disp ...

Heroku Application Dysfunction Limited to Local Machine

Experiencing a strange issue with my Heroku setup. I developed an application using React, JavaScript, Node, and Mongo. When I access the link to my app on my local machine: , I can see the website, but changes are not reflecting when pushed to Heroku. ...

Clearing LocalStorage and Cache upon initial loading in Next.js

Our project requires continuous updates, and currently users are required to manually clear their cache and localStorage data after each update in order to access the new features. Is there a solution to automatically clear all cached data upon user visi ...

Creating a form for adding and editing using React Hook Form

I'm currently working on creating a form that can handle both the creation and editing of a product by passing values through an object. The form functions perfectly for creating a product, but I'm facing challenges in making it work for editing ...

I am having trouble using sass files with the command 'dotnet new react'

I attempted to create an ASP.NET Core application with a React frontend, so I executed the following command: dotnet new react -o <project name> This generated a runnable project. However, the issue arose when it couldn't handle sass files. To ...

Is there a way to keep the background image stationary as I scroll?

As someone who is new to html and CSS, I recently tried to enhance my previous project by incorporating a background image that spans the entire screen size and remains fixed while scrolling up or down. Here is the code snippet: ''' body { ...

Leveraging "setState" in React Native with Promises

I am facing a challenge in updating the state of a React Component with data obtained from an API call. I encountered an issue where using the setState function within the promise resulted in an error "Type Error: _this2.setState is not a function" in Reac ...

Basic game of tic tac toe using JavaScript and jQuery

Teaching myself the ropes of JavaScript/jQuery, I decided to dive into building a simple tic tac toe game. Following this example as a guide, I embarked on creating my own version. While most parts seem to be working smoothly, there's one problem that ...

Creating a grid in JavaScript using a formula

I'm looking to create a grid of objects using JavaScript. Unfortunately, I can't remember the formula and I haven't been able to find it online: var width = 113; var height = 113; var col = 10; ...

Having difficulties utilizing React Syntax Highlighter in Next.js 13 with Sanity version 3

Hello there, I've encountered a problem with my project while using Sanity v3 and React Syntax Highlighter. Initially, I had success displaying my code in the browser by utilizing the Refactor library after following a tutorial on the Code Input by Sa ...

Stop MatDialog instance from destroying

In my application, I have a button that triggers the opening of a component in MatDialog. This component makes API calls and is destroyed when the MatDialog is closed. However, each time I open the MatDialog for the second time by clicking the button agai ...

Disable the Tooltip Bootstrap feature

Based on the documentation, it seems possible to disable the functionality by using $('body').off('.alert.data-api'). I attempted to do the same for tooltips by running $('body').off('.tooltip.data-api') in the Jav ...

Update not being displayed on child component's UI

I am having an issue with two parent components, FirstParent and SecondParent, both of which share a common child component called Child. When I click on the Icon within FirstParent, the Redux state updates successfully and the UI displays the Text value ...

What are the steps to create a transparent center in a barcode scanner?

As part of my project, I am developing a barcode scanner using expo-barcode-scanner. The design I have currently implemented features a fully transparent screen. However, my goal is to create a design where only the QR code square is transparent. <Ba ...

My strategies for addressing caching problems in my ReactJS site

Currently tackling ReactJS projects on a website with the URL . Things seem to be running smoothly, until my SEO-savvy friend pointed out an issue with caches. He advised me to visit this cache URL: , where Google should display the main page but instead s ...

Tips for integrating NPM Modules with Flask

As I deploy my Python application with Flask using the render_template() function onto a webpage, I am also attempting to integrate some JavaScript modules using npm. Even though I have installed the necessary modules in the static folder along with all my ...

The error at line 72 of proxyConsole.js is: TypeError - Unable to access the 'default' property of an undefined object

I am new to using react redux loading bar and redux forms After clicking a button, I want the loading bar to display. The issue arises when I try to load the loading bar, resulting in the following error message: proxyConsole.js:72 TypeError: Cannot read p ...

The intricate procedure behind applying a blur effect using CSS3 filters

MDN documentation explains that the filter blur function applies a Gaussian blur to the input image. After comparing it with OpenCV's GaussianBlur, I noticed that their effects are not identical. I am looking to achieve a similar effect using CSS3&ap ...

`Jalali Calendar Compatibility Problem with Material UI Pickers`

Encountering issues with using Material-UI pickers in my react application for implementing the Jalali calendar. The current package versions being used are: "@date-io/jalaali": "^1.3.13", "@date-io/moment": "^1.3.13", "@material-ui/core": "^4.8.3", "@mat ...

Verify whether the chosen options from a dropdown list coincide with a predetermined value

I am working with a form that generates dropdown lists dynamically. <c:forEach var="companyList" items="${company.detailList}" varStatus="status"> <tr> <td>c:out value="${companyList.employeeName}" /></td> <td> <select ...