Tailwind CSS Course
Tailwind CSS
/
Advanced

Class Variance Authority (CVA)

Definition

A popular JavaScript library (`class-variance-authority`) used to construct highly complex, scalable React components with multiple visual variants (e.g., solid, outline, ghost) using Tailwind classes.

Explain Like I'm New

Building a React Button component that takes an `intent` prop (primary/danger) and a `size` prop (small/large). CVA elegantly handles the messy logic of stitching all those different Tailwind classes together based on the props you pass in.

Real World Example

The foundation of the wildly popular `shadcn/ui` component library. It uses CVA to manage all component variants.

Common Use Cases

  • •Enterprise component libraries
  • •Design systems

Interactive Example

import { cva } from 'class-variance-authority';

// Define the component's variations
const buttonVariants = cva(
  "font-semibold rounded transition-colors focus:ring-2", // Base classes always applied
  {
    variants: {
      intent: {
        primary: "bg-blue-500 hover:bg-blue-600 text-white",
        danger: "bg-red-500 hover:bg-red-600 text-white",
        outline: "border-2 border-gray-500 text-gray-700 hover:bg-gray-100",
      },
      size: {
        sm: "px-2 py-1 text-sm",
        md: "px-4 py-2 text-base",
        lg: "px-6 py-3 text-lg",
      }
    },
    defaultVariants: { intent: "primary", size: "md" } // Fallbacks
  }
);

// Usage in React:
// <Button intent="danger" size="lg">Delete</Button>
function Button({ intent, size, className, ...props }) {
  // CVA merges the variant classes with any extra custom classes passed in
  return <button className={buttonVariants({ intent, size, className })} {...props} />;
}

Interview Questions

basic

  • What problem does CVA solve when building Tailwind components in React?

intermediate

  • Does CVA conflict with Tailwind, or complement it?

Flash Cards

Question

What problem?

Click to reveal answer
Answer

It solves 'Class Name Spaghetti'. Writing massive ternary operators (`className={intent === 'primary' ? 'bg-blue-500' : 'bg-red-500'}`) becomes unreadable. CVA organizes these variants neatly into an object.

Question

Conflict or complement?

Click to reveal answer
Answer

It complements it perfectly. CVA is just a JavaScript string-builder. It generates the final string of Tailwind classes to give to the DOM.