Migration from CVA
css-variants has a similar API to CVA (Class Variance Authority), making migration straightforward.
Key Differences
Section titled “Key Differences”| Feature | CVA | css-variants |
|---|---|---|
| Base styles | First argument | base property |
| Compound class key | class | className |
| Custom merger | class in call | classNameResolver in config |
| Slot variants | Not built-in | scv function |
| Style variants | Not built-in | sv and ssv functions |
Basic Migration
Section titled “Basic Migration”Before (CVA)
Section titled “Before (CVA)”import { cva } from 'class-variance-authority'
const button = cva('btn base-styles', { variants: { color: { primary: 'bg-blue-600 text-white', secondary: 'bg-gray-200 text-gray-900', }, size: { sm: 'px-3 py-1 text-sm', lg: 'px-6 py-3 text-lg', }, }, defaultVariants: { color: 'primary', size: 'sm', },})After (css-variants)
Section titled “After (css-variants)”import { cv } from 'css-variants'
const button = cv({ base: 'btn base-styles', // Move to 'base' property variants: { color: { primary: 'bg-blue-600 text-white', secondary: 'bg-gray-200 text-gray-900', }, size: { sm: 'px-3 py-1 text-sm', lg: 'px-6 py-3 text-lg', }, }, defaultVariants: { color: 'primary', size: 'sm', },})Compound Variants
Section titled “Compound Variants”Before (CVA)
Section titled “Before (CVA)”const button = cva('btn', { variants: { /* ... */ }, compoundVariants: [ { color: 'primary', size: 'lg', class: 'shadow-lg', // CVA uses 'class' }, ],})After (css-variants)
Section titled “After (css-variants)”const button = cv({ base: 'btn', variants: { /* ... */ }, compoundVariants: [ { color: 'primary', size: 'lg', className: 'shadow-lg', // css-variants uses 'className' }, ],})Runtime Class Overrides
Section titled “Runtime Class Overrides”Before (CVA)
Section titled “Before (CVA)”button({ color: 'primary', class: 'mt-4' })After (css-variants)
Section titled “After (css-variants)”button({ color: 'primary', className: 'mt-4' })Type Extraction
Section titled “Type Extraction”Before (CVA)
Section titled “Before (CVA)”import { type VariantProps } from 'class-variance-authority'
const button = cva('btn', { /* ... */ })
type ButtonProps = VariantProps<typeof button>After (css-variants)
Section titled “After (css-variants)”const button = cv({ /* ... */ })
type ButtonProps = Parameters<typeof button>[0]New Features in css-variants
Section titled “New Features in css-variants”After migrating, you can take advantage of features not available in CVA:
Slot Variants
Section titled “Slot Variants”import { scv } from 'css-variants'
const card = scv({ slots: ['root', 'header', 'content', 'footer'], base: { root: 'rounded-lg border', header: 'p-4 border-b', content: 'p-4', footer: 'p-4 border-t', }, variants: { variant: { default: { root: 'border-gray-200' }, primary: { root: 'border-blue-200' }, }, },})Style Variants
Section titled “Style Variants”import { sv } from 'css-variants'
const box = sv({ base: { display: 'flex', borderRadius: '8px', }, variants: { size: { sm: { padding: '8px' }, lg: { padding: '24px' }, }, },})Migration Checklist
Section titled “Migration Checklist”- Replace
cvaimports withcvfromcss-variants - Move first argument (base classes) to
baseproperty - Change
classtoclassNamein compound variants - Change
classtoclassNamein runtime overrides - Update
VariantPropstype extraction to useParameters<typeof fn>[0] - (Optional) Convert multi-element components to use
scv