---
title: "Installation"
description: "Install unocss-variants, configure an UnoCSS uv layer, and create your first recipe."
canonical_url: "https://vinicunca.dev/unocss-variants/getting-started/installation"
---
# Installation

> Install unocss-variants, configure an UnoCSS uv layer, and create your first recipe.

## Setup UnoCSS

UnoCSS Variants only builds class strings. You still need [UnoCSS](https://unocss.dev/) in the project so those utilities exist in CSS.

## Install the package

```bash [pnpm]
pnpm add unocss-variants
```

```bash [npm]
npm install unocss-variants
```

```bash [bun]
bun add unocss-variants
```

Published version **1.5.0** is `unocss-variants` on npm. The source at that tag exports `uv` and `cn`. See the [cn](https://vinicunca.dev/unocss-variants/concepts/cn) page for a mismatch between those types and the published JavaScript bundle.

## Configure a `uv` layer

Because `uv` never merges utilities, give later styles a higher CSS layer. Add a `uv` layer and prefix classes that must win with `uno-layer-uv:`:

```ts [uno.config.ts]
import { defineConfig } from 'unocss';

export default defineConfig({
  layers: {
    uv: 10
  }
});
```

Higher numbers are emitted later and win over the default layer. Full explanation: [Layers & conflict resolution](https://vinicunca.dev/unocss-variants/concepts/layers).

## Your first recipe

Define a recipe with `uv`, then call it like a function. `defaultVariants` keep call sites short.

```vue
<template>
  <uv-button :uv="{
    base: 'font-medium bg-blue-500 color-white rounded-full active:opacity-80',
    variants: {
      color: {
        primary: 'bg-blue-500 color-white',
        secondary: 'bg-purple-500 color-white'
      },
      size: {
        sm: 'text-sm',
        md: 'text-base',
        lg: 'px-4 py-3 text-lg'
      }
    },
    defaultVariants: {
      size: 'md',
      color: 'primary'
    },
    compoundVariants: [
      {
        size: [
          'sm',
          'md'
        ],
        class: 'px-3 py-1'
      }
    ]
  }" as="button" color="secondary" size="sm">
    <p>
      Click me
    </p>
  </uv-button>
</template>
```

```vue
<script setup>
import { uv } from 'unocss-variants';

const button = uv({
  base: 'font-medium bg-blue-500 color-white rounded-full active:opacity-80',
  variants: {
    color: {
      primary: 'bg-blue-500 color-white',
      secondary: 'bg-purple-500 color-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'
  }
});
</script>

<template>
  <button :class="button({ size: 'sm', color: 'secondary' })">
    Click me
  </button>
</template>
```

## Editor setup

Install the [UnoCSS VS Code extension](https://marketplace.visualstudio.com/items?itemName=antfu.unocss) so utilities inside recipe strings are detected. The default extractor picks up quoted class strings in `uv({ ... })` calls.

There is no Tailwind `classRegex` to copy — UnoCSS Variants is not Tailwind, and it does not ship IntelliSense for a `responsiveVariants` map.

## Next steps

[**Frameworks**](https://vinicunca.dev/unocss-variants/getting-started/frameworks)

Vue `class`, React `className`, Svelte, and vanilla.

[**Variants**](https://vinicunca.dev/unocss-variants/concepts/variants)

Axes, booleans, compound rules, and defaults.

[**Slots**](https://vinicunca.dev/unocss-variants/concepts/slots)

Multi-part components and compound slots.


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
