You’ll often see cn, clsx, and twMerge in Tailwind projects, especially if you’re using shadcn/ui.
But what are they, and why do we use them?
These utilities help manage Tailwind classes in a clean, scalable way. Instead of messy string concatenation, they handle conditional logic, remove duplicates, and resolve conflicts automatically.
Let’s take an example to understand why and how they’re used.
Suppose you are creating a Card component that accepts children and renders with some default styling. But it’s not always the case that you only want the default styles sometimes you need to provide your own Tailwind utility classes.
The common approach is to accept a className prop and pass it down to the Card.
However, since Tailwind utilities are just strings, you might be tempted to concatenate them like this:
<div className={"backdrop-blur-md " + className}>{children}</div>
+ becomes unreadable and unmaintainable.className is undefined or null, they get converted into literal strings ("undefined", "null") in the final HTML.clsx handles falsy values automatically, so you don’t end up with "undefined" or "null" in your class list.
import { clsx } from "clsx";
function Card({ children, className }: { children: React.ReactNode; className?: string }) {
return (
<div className={clsx("backdrop-blur-md", className)}>
{children}
</div>
);
}
clsx