When building React components with Tailwind CSS, you often need to:
Manually handling these cases can be messy. That’s where cn comes in.
cn?cn is a helper function that:
className props to override defaults, giving users full control over styles.Though cn is commonly used in shadcn/ui, it's a general-purpose utility that you can use in any React + Tailwind project.
cn Works InternallyA typical cn function is implemented like this:
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
clsx(inputs): Combines and filters out false, null, or undefined values.twMerge(...): Ensures conflicting Tailwind classes are resolved, with later ones taking priority.Now, let’s see why this is useful.
cnImagine a Button component:
export function Button({ className }: { className?: string }) {
return (
<button className={`px-4 py-2 bg-blue-500 text-white ${className}`}>
Click Me
</button>
);
}
🔴 Issue:
<Button className="bg-red-500" />, the button will have both bg-blue-500 and bg-red-500, potentially causing conflicts.cn to Fix It // Assuming you've placed `cn` in `lib/utils.ts`
export function Button({ className }: { className?: string }) {
return (
<button className={cn("px-4 py-2 bg-blue-500 text-white", className)}>
Click Me
</button>
);
}
Now, if someone does:
<Button className="bg-red-500 p-2" />
The final result will be:
<button class="bg-red-500 text-white p-2">Click Me</button>
bg-red-500 replaces bg-blue-500p-2 replaces p-4We can take this further by using props to conditionally apply styles.
Card Component with Conditional Stylingexport function Card({
className,
isHighlighted,
hasShadow,
}: {
className?: string;
isHighlighted?: boolean;
hasShadow?: boolean;
}) {
return (
<div
className={cn(
"p-4 border rounded",
isHighlighted && "bg-yellow-200",
hasShadow && "shadow-lg",
className
)}
>
Card Content
</div>
);
}
<Card isHighlighted hasShadow className="border-red-500" />
<div class="p-4 border rounded bg-yellow-200 shadow-lg border-red-500">
Card Content
</div>
bg-yellow-200 added due to isHighlightedshadow-lg added due to hasShadowborder-red-500 replaces borderThis approach makes components more reusable and customizable without losing control over default styles.
cnUse cn whenever:
✔ You need to merge Tailwind classes dynamically.
✔ You want to allow className overrides safely.
✔ You need to conditionally apply styles based on props.
✔ You want to prevent class conflicts in reusable components.
cn isn't just for shadcn/ui—it’s useful for any React + Tailwind project.By mastering cn, you'll improve your workflow and make your React components more flexible and maintainable.