When to write custom CSS or extract components
Tailwind is not a rule that forbids CSS files. Use custom CSS for complex pseudo-elements, intricate animations, third-party overrides, or selectors that become awkward as utilities. Use components for repeated UI structures with meaningful behavior or API boundaries.
In React, extract a component when repetition, semantic meaning, behavior, or testing needs justify it—not merely because a class string has many tokens. A PrimaryButton can centralize interaction states and accessibility; a generic wrapper with dozens of boolean props can become harder to maintain than the original markup.
React component with a class map
const buttonVariants = {
primary: "bg-blue-600 text-white hover:bg-blue-700 focus-visible:outline-blue-600",
secondary: "border border-slate-300 bg-white text-slate-900 hover:bg-slate-50 focus-visible:outline-slate-500",
};
export function Button({ variant = "primary", children, ...props }) {
return (
<button
{...props}
className={`inline-flex items-center justify-center rounded-lg px-4 py-2.5 text-sm font-semibold focus-visible:outline-2 focus-visible:outline-offset-2 ${buttonVariants[variant]}`}
>
{children}
</button>
);
}💡 The variant map contains complete class candidates. The component shares structure and focus behavior while keeping the visual difference explicit. For production TypeScript, constrain
variant to the supported keys and merge caller classes with a deliberate class-merging strategy if overrides are allowed.Knowledge Check
When is extracting a Tailwind pattern into a component most useful?