Tailwind CSS Patterns That Actually Scale: cva, cn(), and Design Tokens
Tailwind CSS is fast to write but easy to write badly. After building a dozen production UIs, these are the patterns that produce clean, maintainable Tailwind code. 1. The cn() Utility Is Not Optio...

Source: DEV Community
Tailwind CSS is fast to write but easy to write badly. After building a dozen production UIs, these are the patterns that produce clean, maintainable Tailwind code. 1. The cn() Utility Is Not Optional Every Tailwind project needs the class composition utility: // src/lib/utils.ts import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } Without twMerge, conflicting classes accumulate: // BAD: both p-4 and p-8 in the class string -- p-4 wins (wrong) <div className={`p-4 ${isLarge ? "p-8" : ""}`}> // GOOD: twMerge resolves conflicts, p-8 wins when isLarge is true <div className={cn("p-4", isLarge && "p-8")}> Without clsx, you get ugly conditional logic: // BAD className={`base-class ${condition1 ? "class-a" : ""} ${condition2 ? "class-b" : ""}`} // GOOD className={cn("base-class", condition1 && "class-a", condition2 && "class-b")} 2. Component Varia