Simplify Your CSS Logic with Classnames: A Must-Have Tool for Frontend Developers

A developer using a computer to write code
Photo by charlesdeluvio on Unsplash

Styling web applications and user interfaces can be a challenging task, especially when dealing with complex designs and dynamic content. One of the most important aspects of styling is the ability to conditionally apply CSS classes based on certain conditions, such as user interaction or data state. This is where the Classnames utility library comes in handy. Classnames is a lightweight JavaScript library that makes it easy to conditionally join CSS class names together based on simple logic.

In this article, we’ll take a closer look at the Classnames library and explore how it can simplify the process of dynamically applying CSS classes to elements in your web applications. We’ll also provide some practical examples of how you can use Classnames with popular CSS frameworks like Tailwind, Bootstrap, and Material UI to create highly customizable and responsive user interfaces. Whether you’re a seasoned web developer or just getting started, Classnames is a powerful tool that can help streamline your styling workflow and make your code more readable and maintainable.

Classnames — A simple JavaScript utility for conditionally joining classNames together.

This library is very simple to use. It provides a function that can accept any number of arguments, which can be strings or objects, and then return corresponding class names if the value associated with a given key in the object is truthy. If the value associated with a given key is falsy, that key won’t be included in the output.

When the argument is a string, it’s short for an object with that key set to true. For instance, an argument like active is equivalent to {active: true}. Here are some examples:

classNames('active', 'show'); // => 'active show'

classNames('active', { show: true }); // => 'active show'

classNames({ 'active-show': true }); // => 'active-show'

classNames({ 'active-show': false }); // => ''

classNames({ active: true }, { show: true }); // => 'active show'

classNames({ active: true, show: true }); // => 'active show'

// many arguments of various data types
classNames('active', { show: true, hidden: false }, 'baz', { highlight: true });// => 'active show baz highlight'

// falsy values are just ignored
classNames(null, false, 'show', undefined, 0, 1, { baz: null }, ''); // => 'show 1'

A common scenario where I use this library is to create highly customizable buttons in my React projects. Let me illustrate with an example using Tailwind CSS. I find that Tailwind’s flexible utility classes align well with the types of arguments that this library expects. Typically, I have a CSS file for my project, which I will refer to as styles.css

/** styles.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
.btn {
@apply px-5 py-3 font-medium outline-none rounded-full transition-all duration-200;
}
.btn-primary {
@apply text-white bg-blue-600 hover:bg-blue-400 hover:text-black;
}
.btn-secondary {
@apply text-white bg-blue-600 hover:bg-blue-400 hover:text-black;
}
.btn-outline {
@apply text-blue-600 bg-white hover:bg-blue-400 hover:text-black ring-2 hover:ring-blue-400;
}
}

This code defines some class names such as .btn, .btn-primary.btn-secondary, and .btn-outline using Tailwind CSS. When the code is compiled, Tailwind generates corresponding CSS properties and values for these defined classes. Moving on to the button component:

import React from "react";
import type { ButtonProps } from "./types";
import classNames from "classnames";
import { RiLoader3Line } from "react-icons/ri";

export default function Button({
className,
variant = "primary",
loading = false,
children,
...props
}: ButtonProps) {

return (
<button
className={classNames("btn", {
"btn-primary": variant === "primary",
"btn-secondary": variant === "secondary",
"btn-outline": variant === "outline"
}, className)}
{...props}
>
{loading && (
<RiLoader3Line className="animate-spin !w-4 !h-4 inline-block mr-1" />
)}
{children}
</button>
);
}

This code is an example of how to use the classnames library in a React component to generate dynamic class names based on component props.

The component is a Button component that accepts several props, such as className, variant, loading, and children. The variant prop specifies the type of button to render and can be one of primary, secondary, or outline. The loading prop is a boolean that determines whether to show a loading spinner icon within the button. The children prop is the content of the button, such as text or an icon.

The component then uses the classnames library to generate a dynamic set of class names based on the variant, and className props passed to the component. The resulting class names are passed to the className prop of the button element.

Finally, the component renders a button element with the generated class names, along with the loading spinner icon and children content, if applicable.

Overall, the classnames library provides a convenient way to generate dynamic class names in React components, and can help keep the code clean and readable.

Other ways the classNames function can be made simpler is to shorten its name. Some people do this:

import cls from “classnames”;
// ...

// and use as
className={cls('foo', 'bar')}

Using classnames with Other CSS Frameworks and Styles

The classnames library is not limited to use with Tailwind CSS. It can also be used with other CSS frameworks and styles, such as Bootstrap, Material UI, and custom CSS styles. Here are some examples:

Using classnames with Bootstrap

Bootstrap is a popular CSS framework that provides a set of pre-defined classes for common UI components. Here’s an example of how to use classnames with Bootstrap classes:

import React from "react";
import classNames from "classnames";
import "bootstrap/dist/css/bootstrap.min.css";

export default function Alert({ variant, children }) {
const classes = classNames("alert", {
"alert-primary": variant === "primary",
"alert-secondary": variant === "secondary",
"alert-success": variant === "success",
"alert-danger": variant === "danger",
"alert-warning": variant === "warning",
"alert-info": variant === "info",
"alert-light": variant === "light",
"alert-dark": variant === "dark",
});

return <div className={classes}>{children}</div>;
}

In this example, we’re defining an component that takes in a variant prop and children prop. We’re using classnames to conditionally join together the alert class with one of the pre-defined Bootstrap alert classes based on the variant prop.

Using classnames with Material UI

Material UI is a popular React UI library that provides a set of pre-defined components with customizable styles. Here’s an example of how to use classnames with Material UI classes:

import React from "react";
import classNames from "classnames";
import { makeStyles } from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";

const useStyles = makeStyles((theme) => ({
root: {
"& > *": {
margin: theme.spacing(1),
},
},
primary: {
backgroundColor: theme.palette.primary.main,
color: "white",
},
secondary: {
backgroundColor: theme.palette.secondary.main,
color: "white",
},
}));

export default function CustomButton({ variant, children }) {
const classes = useStyles();

return (
<div className={classes.root}>
<Button
className={classNames({
[classes.primary]: variant === "primary",
[classes.secondary]: variant === "secondary",
})}
>
{children}
</Button>
</div>
);
}

In this example, we’re defining a CustomButton component that takes in a variant prop and children prop. We’re using the makeStyles hook from Material UI to define our custom styles and using classnames to conditionally apply the primary or secondary class based on the variant prop.

Using classnames with Custom CSS Styles

Classnames can also be used with custom CSS styles. Here’s an example of how to use it:

import React from "react";
import classNames from "classnames";
import "./styles.css";

export default function CustomComponent({ isActive, isDisabled, children }) {
const classes = classNames("custom-component", {
"custom-component--active": isActive,
"custom-component--disabled": isDisabled,
});

return <div className={classes}>{children}</div>;
}

In this example, we’re defining a CustomComponent component that takes in an isActive prop, and an isDisabled prop. Is isActive is true, the custom-component-active class is applied to the div element and is isDisabled is true, the custom-component-disabled is applied

In conclusion, the classnames utility is a powerful and convenient tool for generating dynamic class names in React projects. It allows for a flexible and efficient way to conditionally join class names together, simplifying the process of styling and customizing components. Whether you’re working with Tailwind CSS, Bootstrap, or any other CSS framework or style, the classnames utility can be easily integrated into your project. By using the classnames utility, you can write cleaner, more readable code and make your React components more versatile and customizable. So why not give it a try in your next project?

Be sure to check out the Classnames library on npm or GitHub for easy steps on how to include it in your projects. Additionally, you might want to consider the clsx module as a cool alternative to Classnames. It’s a tiny utility (only 228B) that allows you to construct className strings conditionally, and it can serve as a faster and smaller drop-in replacement for the Classnames library.

If you enjoyed this article and would like to receive updates on future content, be sure to follow me on Medium at (Justice Ekemezie) and Twitter at @ttebify.


Simplify Your CSS Logic with Classnames: A Must-Have Tool for Frontend Developers was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Justice Ekemezie

A developer using a computer to write code
Photo by charlesdeluvio on Unsplash

Styling web applications and user interfaces can be a challenging task, especially when dealing with complex designs and dynamic content. One of the most important aspects of styling is the ability to conditionally apply CSS classes based on certain conditions, such as user interaction or data state. This is where the Classnames utility library comes in handy. Classnames is a lightweight JavaScript library that makes it easy to conditionally join CSS class names together based on simple logic.

In this article, we’ll take a closer look at the Classnames library and explore how it can simplify the process of dynamically applying CSS classes to elements in your web applications. We’ll also provide some practical examples of how you can use Classnames with popular CSS frameworks like Tailwind, Bootstrap, and Material UI to create highly customizable and responsive user interfaces. Whether you’re a seasoned web developer or just getting started, Classnames is a powerful tool that can help streamline your styling workflow and make your code more readable and maintainable.

Classnames — A simple JavaScript utility for conditionally joining classNames together.

This library is very simple to use. It provides a function that can accept any number of arguments, which can be strings or objects, and then return corresponding class names if the value associated with a given key in the object is truthy. If the value associated with a given key is falsy, that key won’t be included in the output.

When the argument is a string, it’s short for an object with that key set to true. For instance, an argument like active is equivalent to {active: true}. Here are some examples:

classNames('active', 'show'); // => 'active show'

classNames('active', { show: true }); // => 'active show'

classNames({ 'active-show': true }); // => 'active-show'

classNames({ 'active-show': false }); // => ''

classNames({ active: true }, { show: true }); // => 'active show'

classNames({ active: true, show: true }); // => 'active show'

// many arguments of various data types
classNames('active', { show: true, hidden: false }, 'baz', { highlight: true });// => 'active show baz highlight'

// falsy values are just ignored
classNames(null, false, 'show', undefined, 0, 1, { baz: null }, ''); // => 'show 1'

A common scenario where I use this library is to create highly customizable buttons in my React projects. Let me illustrate with an example using Tailwind CSS. I find that Tailwind’s flexible utility classes align well with the types of arguments that this library expects. Typically, I have a CSS file for my project, which I will refer to as styles.css

/** styles.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
.btn {
@apply px-5 py-3 font-medium outline-none rounded-full transition-all duration-200;
}
.btn-primary {
@apply text-white bg-blue-600 hover:bg-blue-400 hover:text-black;
}
.btn-secondary {
@apply text-white bg-blue-600 hover:bg-blue-400 hover:text-black;
}
.btn-outline {
@apply text-blue-600 bg-white hover:bg-blue-400 hover:text-black ring-2 hover:ring-blue-400;
}
}

This code defines some class names such as .btn, .btn-primary.btn-secondary, and .btn-outline using Tailwind CSS. When the code is compiled, Tailwind generates corresponding CSS properties and values for these defined classes. Moving on to the button component:

import React from "react";
import type { ButtonProps } from "./types";
import classNames from "classnames";
import { RiLoader3Line } from "react-icons/ri";

export default function Button({
className,
variant = "primary",
loading = false,
children,
...props
}: ButtonProps) {

return (
<button
className={classNames("btn", {
"btn-primary": variant === "primary",
"btn-secondary": variant === "secondary",
"btn-outline": variant === "outline"
}, className)}
{...props}
>
{loading && (
<RiLoader3Line className="animate-spin !w-4 !h-4 inline-block mr-1" />
)}
{children}
</button>
);
}

This code is an example of how to use the classnames library in a React component to generate dynamic class names based on component props.

The component is a Button component that accepts several props, such as className, variant, loading, and children. The variant prop specifies the type of button to render and can be one of primary, secondary, or outline. The loading prop is a boolean that determines whether to show a loading spinner icon within the button. The children prop is the content of the button, such as text or an icon.

The component then uses the classnames library to generate a dynamic set of class names based on the variant, and className props passed to the component. The resulting class names are passed to the className prop of the button element.

Finally, the component renders a button element with the generated class names, along with the loading spinner icon and children content, if applicable.

Overall, the classnames library provides a convenient way to generate dynamic class names in React components, and can help keep the code clean and readable.

Other ways the classNames function can be made simpler is to shorten its name. Some people do this:

import cls from “classnames”;
// ...

// and use as
className={cls('foo', 'bar')}

Using classnames with Other CSS Frameworks and Styles

The classnames library is not limited to use with Tailwind CSS. It can also be used with other CSS frameworks and styles, such as Bootstrap, Material UI, and custom CSS styles. Here are some examples:

Using classnames with Bootstrap

Bootstrap is a popular CSS framework that provides a set of pre-defined classes for common UI components. Here’s an example of how to use classnames with Bootstrap classes:

import React from "react";
import classNames from "classnames";
import "bootstrap/dist/css/bootstrap.min.css";

export default function Alert({ variant, children }) {
const classes = classNames("alert", {
"alert-primary": variant === "primary",
"alert-secondary": variant === "secondary",
"alert-success": variant === "success",
"alert-danger": variant === "danger",
"alert-warning": variant === "warning",
"alert-info": variant === "info",
"alert-light": variant === "light",
"alert-dark": variant === "dark",
});

return <div className={classes}>{children}</div>;
}

In this example, we’re defining an component that takes in a variant prop and children prop. We're using classnames to conditionally join together the alert class with one of the pre-defined Bootstrap alert classes based on the variant prop.

Using classnames with Material UI

Material UI is a popular React UI library that provides a set of pre-defined components with customizable styles. Here’s an example of how to use classnames with Material UI classes:

import React from "react";
import classNames from "classnames";
import { makeStyles } from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";

const useStyles = makeStyles((theme) => ({
root: {
"& > *": {
margin: theme.spacing(1),
},
},
primary: {
backgroundColor: theme.palette.primary.main,
color: "white",
},
secondary: {
backgroundColor: theme.palette.secondary.main,
color: "white",
},
}));

export default function CustomButton({ variant, children }) {
const classes = useStyles();

return (
<div className={classes.root}>
<Button
className={classNames({
[classes.primary]: variant === "primary",
[classes.secondary]: variant === "secondary",
})}
>
{children}
</Button>
</div>
);
}

In this example, we’re defining a CustomButton component that takes in a variant prop and children prop. We're using the makeStyles hook from Material UI to define our custom styles and using classnames to conditionally apply the primary or secondary class based on the variant prop.

Using classnames with Custom CSS Styles

Classnames can also be used with custom CSS styles. Here’s an example of how to use it:

import React from "react";
import classNames from "classnames";
import "./styles.css";

export default function CustomComponent({ isActive, isDisabled, children }) {
const classes = classNames("custom-component", {
"custom-component--active": isActive,
"custom-component--disabled": isDisabled,
});

return <div className={classes}>{children}</div>;
}

In this example, we’re defining a CustomComponent component that takes in an isActive prop, and an isDisabled prop. Is isActive is true, the custom-component-active class is applied to the div element and is isDisabled is true, the custom-component-disabled is applied

In conclusion, the classnames utility is a powerful and convenient tool for generating dynamic class names in React projects. It allows for a flexible and efficient way to conditionally join class names together, simplifying the process of styling and customizing components. Whether you’re working with Tailwind CSS, Bootstrap, or any other CSS framework or style, the classnames utility can be easily integrated into your project. By using the classnames utility, you can write cleaner, more readable code and make your React components more versatile and customizable. So why not give it a try in your next project?

Be sure to check out the Classnames library on npm or GitHub for easy steps on how to include it in your projects. Additionally, you might want to consider the clsx module as a cool alternative to Classnames. It’s a tiny utility (only 228B) that allows you to construct className strings conditionally, and it can serve as a faster and smaller drop-in replacement for the Classnames library.

If you enjoyed this article and would like to receive updates on future content, be sure to follow me on Medium at (Justice Ekemezie) and Twitter at @ttebify.


Simplify Your CSS Logic with Classnames: A Must-Have Tool for Frontend Developers was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Justice Ekemezie


Print Share Comment Cite Upload Translate Updates
APA

Justice Ekemezie | Sciencx (2023-02-27T01:39:23+00:00) Simplify Your CSS Logic with Classnames: A Must-Have Tool for Frontend Developers. Retrieved from https://www.scien.cx/2023/02/27/simplify-your-css-logic-with-classnames-a-must-have-tool-for-frontend-developers/

MLA
" » Simplify Your CSS Logic with Classnames: A Must-Have Tool for Frontend Developers." Justice Ekemezie | Sciencx - Monday February 27, 2023, https://www.scien.cx/2023/02/27/simplify-your-css-logic-with-classnames-a-must-have-tool-for-frontend-developers/
HARVARD
Justice Ekemezie | Sciencx Monday February 27, 2023 » Simplify Your CSS Logic with Classnames: A Must-Have Tool for Frontend Developers., viewed ,<https://www.scien.cx/2023/02/27/simplify-your-css-logic-with-classnames-a-must-have-tool-for-frontend-developers/>
VANCOUVER
Justice Ekemezie | Sciencx - » Simplify Your CSS Logic with Classnames: A Must-Have Tool for Frontend Developers. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/02/27/simplify-your-css-logic-with-classnames-a-must-have-tool-for-frontend-developers/
CHICAGO
" » Simplify Your CSS Logic with Classnames: A Must-Have Tool for Frontend Developers." Justice Ekemezie | Sciencx - Accessed . https://www.scien.cx/2023/02/27/simplify-your-css-logic-with-classnames-a-must-have-tool-for-frontend-developers/
IEEE
" » Simplify Your CSS Logic with Classnames: A Must-Have Tool for Frontend Developers." Justice Ekemezie | Sciencx [Online]. Available: https://www.scien.cx/2023/02/27/simplify-your-css-logic-with-classnames-a-must-have-tool-for-frontend-developers/. [Accessed: ]
rf:citation
» Simplify Your CSS Logic with Classnames: A Must-Have Tool for Frontend Developers | Justice Ekemezie | Sciencx | https://www.scien.cx/2023/02/27/simplify-your-css-logic-with-classnames-a-must-have-tool-for-frontend-developers/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.