Handling Conditional Classes in JSX
8 min read
Dynamic Classes in React and Next.js
In JSX, class names are often conditional. Naive string interpolation leads to whitespace bugs and hard-to-read code. The community standard solution is the clsx (or cn) helper.
html
<!-- This is NOT valid JSX, but shows the pattern in pseudo-code:
const cls = clsx(
"rounded-lg px-4 py-2 font-semibold transition-colors",
variant === "primary" && "bg-sky-600 text-white hover:bg-sky-700",
variant === "outline" && "border border-sky-600 text-sky-600 hover:bg-sky-50",
disabled && "opacity-50 cursor-not-allowed",
className
);
-->Many projects (including CPCODELAB) use a cn() utility that merges clsx with tailwind-merge. This handles conflicting utilities: cn("p-4", override && "p-8") correctly outputs just p-8, not both.
html
<!-- Typical cn() setup in src/lib/utils.ts:
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs) { return twMerge(clsx(inputs)); }
-->Install tailwind-merge and clsx together. The cn() pattern is so common that shadcn/ui, Radix, and virtually every modern React component library includes it by default.
Ready to test yourself?
Practice Tailwind CSS— quiz & coding exercises