Quick Start

Install Tailwind Variants, choose default or lite, create your first tv recipe, and set up editor IntelliSense.

Install

npm install tailwind-variants

Conflict resolution is included in the default build. You do not need tailwind-merge unless your app calls it directly elsewhere.

For the lite build (no merge, smaller bundle):

import { tv } from "tailwind-variants/lite";

Your first component

Define a recipe with tv, then call it like a function. Defaults keep call sites short; pass props only when you need to diverge.

import { tv } from 'tailwind-variants';const button = tv({  base: 'inline-flex cursor-pointer items-center justify-center rounded-full font-medium select-none transition-colors',  variants: {    variant: {      primary: 'bg-zinc-900 text-white hover:bg-zinc-800',      secondary: 'border border-zinc-300 bg-zinc-50 text-zinc-900 hover:bg-zinc-100',      tertiary: 'text-zinc-700 hover:bg-zinc-200/70 hover:text-zinc-950'    },    size: {      sm: 'h-8 px-3 text-sm',      md: 'h-10 px-4 text-sm'    }  },  defaultVariants: {    variant: 'primary',    size: 'md'  }});<button className={button()}>Default button</button><button className={button({ variant: 'secondary', size: 'sm' })}>  Click me</button><button className={button({ class: 'w-full' })}>Full width</button>

Editor setup

VS Code IntelliSense

So Tailwind CSS IntelliSense can complete classes inside tv strings, add this to your VS Code settings:

{
  "tailwindCSS.experimental.classRegex": [
    ["tv\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
  ]
}

Prettier

If you use prettier-plugin-tailwindcss, include tv in the function list so class order stays consistent:

// prettier.config.js
module.exports = {
  plugins: ["prettier-plugin-tailwindcss"],
  tailwindFunctions: ["tv", "cn", "cx"],
};

Framework agnostic

Tailwind Variants is framework-agnostic. Use the class string with any framework or vanilla JS:

import { tv } from "tailwind-variants";

const button = tv({
  base: "inline-flex cursor-pointer items-center justify-center rounded-md px-4 py-2 text-sm font-medium select-none",
  variants: {
    color: {
      primary: "bg-blue-600 text-white",
      secondary: "bg-zinc-200 text-zinc-900",
    },
  },
  defaultVariants: {
    color: "primary",
  },
});

React

<button className={button({ color: "primary" })}>Save</button>

Vue

<button :class="button({ color: 'primary' })">Save</button>

Svelte

<button class={button({ color: 'primary' })}>Save</button>

Solid

<button class={button({ color: "primary" })}>Save</button>

Angular

<button [class]="button({ color: 'primary' })">Save</button>

Vanilla

element.className = button({ color: "primary" });

On this page