How to Implement Multiple Classnames in NextJS
Jasser Mark Arioste
Hello, hustlers! In this tutorial, you'll learn the best practice to implement multiple classnames in React or NextJS.
The Problem #
If you're using multiple classNames to style your components in React, things can go ugly really quickly. Especially if you have to use conditional classNames. In this tutorial, we'll explore how to implement multiple conditional classNames in React or NextJS.
Ways to Implement Multiple Classnames #
Here are the ways to implement multiple classNames that I know of:
- Using string interpolation or concatenation
- Using utility packages like classnames and clsx to handle toggling of classes. I recommend using this approach
Using String Interpolation or Concatenation #
As a beginner, this is what we usually do at first. But you'll soon realize that it becomes very hard to maintain and the code will be less readable. If you're using TailwindCSS for styling, the problem becomes exponentially apparent.
Here's an example:
import React, { ComponentPropsWithRef } from "react"; type Props = ComponentPropsWithRef<"button">; const MyButton = (props: Props) => { const disabledClass = props.disabled ? "disabled opacity-60 pointer-events-none" : ""; const hoverClass = "hover:bg-indigo-700"; return ( <button {...props} className={`${disabledClass} ${hoverClass} bg-indigo-500 text-indigo-50 p-2`} /> ); }; export default MyButton;
123456789101112131415161718
As you can see, the more you use string interpolation, the less readable the code becomes. if you want to see what the value of thedisabledClass
constant is, you have to scroll up to see the code. In other words, you don't have the whole class list at a glance. This becomes more apparent in production-grade applications where there are a lot of component states to take care of.
Next, we'll use utility packages to make our lives easier:
Using Utility Packages #
Currently, there are two utility packages that solve the problem above: classnames and clsx. They don't have any difference aside from clsx being a bit smaller than classnames. Both packages are less than 500 bytes in size so it doesn't matter what you choose. Just a preference to see which package name sounds more cool.
First, we have to install the package, you can choose either one:
yarn add clsx
# or
yarn add classnames
Now let's refactor our code.
Using classnames package: #
import cn from "classnames"; import React, { ComponentPropsWithRef } from "react"; type Props = ComponentPropsWithRef<"button">; const MyButton = (props: Props) => { return ( <button {...props} className={cn({ "hover:bg-indigo-700": true, "bg-indigo-500 text-indigo-50 p-2": true, "disabled opacity-60 pointer-events-none": props.disabled, })} /> ); }; export default MyButton;
12345678910111213141516171819
Now, we can see all the classes used by the component without scrolling up.
In line 10, we use the cn
function and pass an object where the keys are the classes that we want to toggle, and the values are boolean values that may or may not be based on the component's state.
In line 11, the "hover:bg-indigo-700"
class will always be rendered since its value is always true
. However, on line 13, the "disabled opacity-60 pointer-events-none"
will only be rendered if props.disabled
is true
.
Here's the output:
// <MyButton/> <button class="hover:bg-indigo-700 bg-indigo-500 text-indigo-50 p-2"/> // <MyButton disabled/> <button disabled="" class="hover:bg-indigo-700 bg-indigo-500 text-indigo-50 p-2 disabled opacity-60 pointer-events-none"/>
12345
Using clsx
package:
#
Using clsx
package is pretty much the same as the classnames
package. We just need to change a couple of lines:
import clsx from "clsx"; import React, { ComponentPropsWithRef } from "react"; type Props = ComponentPropsWithRef<"button">; const MyButton = (props: Props) => { return ( // <button {...props} className={clsx({ "hover:bg-indigo-700": true, "bg-indigo-500 text-indigo-50 p-2": true, "disabled opacity-60 pointer-events-none": props.disabled, })} /> ); }; export default MyButton;
1234567891011121314151617181920
Conclusion #
You learned how to implement multiple class names in NextJS so that it will be more maintainable, readable, and more importantly production-grade.
If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on GitHub.
Other Alternative Packages #
There's one other package that's available which is classcat.
Resources #
- classnames and clsx npm page
Credits: Image by Matt Hardy from Pixabay