1. Cleaner, More Readable Code
Using cn keeps your JSX clean and easy to read. The className attribute won’t be cluttered with complicated strings and conditional logic. You will spend less time figuring out which classes go with each component. Your teammates, or your future self, will appreciate the clarity.
Here’s a simple example showing how cn keeps things neat:
Without cn:
<div className={`${isActive ? 'bg-green-500' : 'bg-red-500'} ${hasError ? 'border-red-500' : ''} ${isDisabled ? 'opacity-50' : ''}`}>
Content
</div>
With cn:
<div className={cn(
'p-4',
isActive ? 'bg-green-500' : 'bg-red-500',
hasError && 'border-red-500',
isDisabled && 'opacity-50'
)}>
Content
</div>
You can see how much more readable and organized the cn version is.
2. Avoiding Conflicting Classes
Tailwind CSS provides many utility classes that can sometimes conflict. For example, using both bg-red-500 and bg-blue-500 in the same component will apply the last class. This can be confusing and may cause bugs.
Without twMerge:
<div className="bg-red-500 bg-blue-500">
This will have only one background color (blue), but it's not clear.
</div>
With twMerge and cn:
<div className={cn('bg-red-500', 'bg-blue-500')}>
Only the last class will be applied, which is `bg-blue-500`, avoiding the conflict.
</div>
The twMerge function in cn ensures that conflicting Tailwind CSS classes are handled properly, leaving only the last one applied.
3. Improves Component Reusability
When building components, you want them to be reusable and flexible. With cn, you can easily apply different styles based on the props passed to the component, without having to repeat yourself.
For example, let’s say you have a Card component that can have different styles depending on whether it’s highlighted or not:
const Card = ({ isHighlighted }) => {
return (
<div className={cn('p-4 border rounded', isHighlighted ? 'bg-yellow-100' : 'bg-white')}>
This is a {isHighlighted ? 'Highlighted' : 'Normal'} Card
</div>
);
};
In this example, cn makes it easy to manage dynamic styles based on the isHighlighted prop, keeping the code concise and reusable.
4. Supports Various Input Types
The cn function can handle different types of inputs, such as strings, arrays, or objects. This flexibility makes it adaptable to many scenarios.
- Strings: Simple class names like
"bg-blue-500".
- Arrays: You can pass arrays of class names, and
cn will join them.
- Objects: You can conditionally apply class names using objects, where the key is the class name and the value is a condition (true or false).
For example:
<div className={cn('p-4', { 'bg-blue-500': isPrimary, 'bg-gray-500': !isPrimary })}>
Dynamic Background
</div>
This gives you the flexibility to manage conditional logic in a clean, readable way.