Skip to content
Docs
Introduction

Introduction

tailwind-variants banner

Tailwind Variants a first-class variant API library for TailwindCSS (opens in a new tab).

Key features

Variants

Since Stitches (opens in a new tab) introduced variants, we became big fans of them, they are a great way to create a consistent design system, so we created Tailwind Variants to bring them to TailwindCSS.


import { tv } from 'tailwind-variants';
 
const button = tv({
  base: 'font-medium bg-blue-500 text-white rounded-full active:opacity-80',
  variants: {
    color: {
      primary: 'bg-blue-500 text-white',
      secondary: 'bg-purple-500 text-white'
    },
    size: {
      sm: 'text-sm',
      md: 'text-base',
      lg: 'px-4 py-3 text-lg'
    }
  },
  compoundVariants: [
    {
      size: ['sm', 'md'],
      class: 'px-3 py-1'
    }
  ],
  defaultVariants: {
    size: 'md',
    color: 'primary'
  }
});
 
return (
  <button className={button({ size: 'sm', color: 'secondary' })}>
    Click me
  </button>
);

To learn more about variants, check the variants page.

Responsive variants

Tailwind Variants allows you to apply variants to different screen sizes.


import { tv } from 'tailwind-variants';
 
const button = tv(
  {
    base: 'font-semibold text-white py-1 px-3 rounded-full active:opacity-80',
    variants: {
      color: {
        primary: 'bg-blue-500 hover:bg-blue-700',
        secondary: 'bg-purple-500 hover:bg-purple-700',
        success: 'bg-green-500 hover:bg-green-700',
        error: 'bg-red-500 hover:bg-red-700'
      }
    }
  },
  {
    responsiveVariants: ['xs', 'sm', 'md'] // `true` to apply to all screen sizes
  }
);
 
button({
  color: {
    initial: 'primary',
    xs: 'secondary',
    sm: 'success',
    md: 'error'
  }
});
 
/**
 * Result:
 * font-semibold text-white py-1 px-3 rounded-full active:opacity-80 bg-blue-500 hover:bg-blue-700
 * xs:bg-purple-500 xs:hover:bg-purple-700 sm:bg-green-500 sm:hover:bg-green-700 md:bg-red-500
 * md:hover:bg-red-700
 */

To learn more about responsive variants, check the variants page and the slots page

Split components into multiple slots

You can style multiple components at once using the slots property.


import { tv } from 'tailwind-variants';
 
const card = tv({
  slots: {
    base: 'md:flex bg-slate-100 rounded-xl p-8 md:p-0 dark:bg-gray-900',
    avatar:
      'w-24 h-24 md:w-48 md:h-auto md:rounded-none rounded-full mx-auto drop-shadow-lg',
    wrapper: 'flex-1 pt-6 md:p-8 text-center md:text-left space-y-4',
    description: 'text-md font-medium',
    infoWrapper: 'font-medium',
    name: 'text-sm text-sky-500 dark:text-sky-400',
    role: 'text-sm text-slate-700 dark:text-slate-500'
  }
});
 
const { base, avatar, wrapper, description, infoWrapper, name, role } = card();
 
return (
  <figure className={base()}>
    <img
      className={avatar()}
      src="/intro-avatar.png"
      alt=""
      width="384"
      height="512"
    />
    <div className={wrapper()}>
      <blockquote>
        <p className={description()}>
          “Tailwind variants allows you to reduce repeated code in your project
          and make it more readable. They fixed the headache of building a
          design system with TailwindCSS.”
        </p>
      </blockquote>
      <figcaption className={infoWrapper()}>
        <div className={name()}>Zoey Lang</div>
        <div className={role()}>Full-stack developer, NextUI</div>
      </figcaption>
    </div>
  </figure>
);

To learn more about slots and how to use them, check out the Slots page.

Overrides

Tailwind Variants provides a class / className prop for overriding classes on any component.


import { tv } from 'tailwind-variants';
 
const button = tv({
  base: 'font-semibold text-white py-1 px-3 rounded-full active:opacity-80',
  variants: {
    color: {
      primary: 'bg-blue-500 hover:bg-blue-700',
      secondary: 'bg-purple-500 hover:bg-purple-700',
      success: 'bg-green-500 hover:bg-green-700',
      error: 'bg-red-500 hover:bg-red-700'
    }
  }
});
 
button({
  color: 'secondary',
  class: 'bg-pink-500 hover:bg-pink-500' // overrides the color variant
});
 
/**
 * Result:
 * font-semibold text-white py-1 px-3 rounded-full active:opacity-80 bg-pink-500 hover:bg-pink-500
 */

To learn more the overrides, check out this page.

Components composition

Tailwind Variants allows you to compose components using the extend parameter. It automatically merges the classes, slots, variants, defaultVariants and compoundVariants of the extended component.


import { tv } from 'tailwind-variants';
 
const baseButton = tv({
  base: [
    'font-semibold',
    'dark:text-white',
    'py-1',
    'px-3',
    'rounded-full',
    'active:opacity-80',
    'bg-zinc-100',
    'hover:bg-zinc-200',
    'dark:bg-zinc-800',
    'dark:hover:bg-zinc-800'
  ]
});
 
const buyButton = tv({
  extend: baseButton,
  base: [
    'text-sm',
    'text-white',
    'rounded-lg',
    'shadow-lg',
    'uppercase',
    'tracking-wider',
    'bg-blue-500',
    'hover:bg-blue-600',
    'shadow-blue-500/50',
    'dark:bg-blue-500',
    'dark:hover:bg-blue-600'
  ]
});
 
return (
  <div className="flex gap-3">
    <button className={baseButton()}>Button</button>
    <button className={buyButton()}>Buy button</button>
  </div>
);
 
/**
 * buyButton();
 *
 * Result:
 * font-semibold dark:text-white py-1 px-3 active:opacity-80 text-sm text-white rounded-lg
 * shadow-lg shadow-blue-500/50 uppercase tracking-wider bg-blue-500 hover:bg-blue-600
 * dark:bg-blue-500 dark:hover:bg-blue-600
 */

To learn more about Components composition, check out this page.

Developer experience

Tailwind Variants is built with developer experience in mind, it provides a great autocomplete experience thanks to the fully-typed API, so when using TypeScript, slots, values, and breakpoints will be auto-completed for you.

Automatic conflict resolution

Tailwind Variants implements tailwind-merge (opens in a new tab) under the hood, so it will efficiently merge your classes, so you don't have to worry about TailwindCSS class conflicts.

Framework agnostic

Tailwind Variants is a utility library that works with any framework. It's not tied to React.

Community

We're excited to see the community adopt NextUI, raise issues, and provide feedback. Whether it's a feature request, bug report, or a project to showcase, please get involved!

Credits

Tailwind Variants is heavily inspired by Stitches (opens in a new tab) and CVA (opens in a new tab).

Special thanks to Tianen Pang (opens in a new tab) for helping with the API design and library creation.

Special thanks to Junior Garcia (opens in a new tab) for building the library and the documentation.

Special thanks to Mark Skelton (opens in a new tab) for mantaining the library and the documentation.

Special thanks to Joe Bell (opens in a new tab) for creating CVA (opens in a new tab) it served as a great inspiration for this library.