css-variants is no longer maintained. Use @lynstack/class-recipe: faster, stricter types, and React Native support. Migrate →
No longer maintained. Migrate to class-recipe →
css-variants is no longer maintained. Use @lynstack/class-recipe: faster, stricter types, and React Native support. Migrate →
No longer maintained. Migrate to class-recipe →
@lynstack/recipe, with the same config everywhere.@lynstack/native-recipe builds React Native style objects, and returns the same frozen style for the same variants, so the style prop keeps its identity between renders.npm uninstall css-variantsnpm install @lynstack/class-recipeclass-recipe ships as an ES module only and requires TypeScript 5.4 or newer for its types.
| css-variants | Replacement |
|---|---|
cx() | cx from @lynstack/class-recipe |
cv() | cva from @lynstack/class-recipe |
scv() | sva from @lynstack/class-recipe |
classNameResolver option | createRecipes({ join }), such as createRecipes({ join: twMerge }) |
sv(), ssv() in React Native | createStyleRecipe and createSlotStyleRecipe from @lynstack/native-recipe |
sv(), ssv() on the web | A recipe kind of @lynstack/recipe that merges style objects |
The config keeps base, variants, compoundVariants, and defaultVariants. A compound variant moves its conditions under variants:
import { cv } from 'css-variants'
const button = cv({ base: 'rounded font-medium', variants: { color: { primary: 'bg-blue-600 text-white', secondary: 'bg-gray-200 text-gray-800', }, size: { sm: 'px-3 py-1.5 text-sm', lg: 'px-6 py-3 text-lg', }, }, compoundVariants: [{ color: 'primary', size: 'lg', className: 'shadow-lg' }], defaultVariants: { color: 'primary', size: 'sm' },})import { cva } from '@lynstack/class-recipe'
const button = cva({ base: 'rounded font-medium', variants: { color: { primary: 'bg-blue-600 text-white', secondary: 'bg-gray-200 text-gray-800', }, size: { sm: 'px-3 py-1.5 text-sm', lg: 'px-6 py-3 text-lg', }, }, compoundVariants: [{ variants: { color: 'primary', size: 'lg' }, className: 'shadow-lg' }], defaultVariants: { color: 'primary', size: 'sm' },})Slot recipes move the same way: scv becomes sva, with the same slots, and a compound variant keeps its classNames and moves its conditions under variants.
cx(...) turns an array or an object into one.The class-recipe docs describe every option, and its guides to migrating from class-variance-authority and tailwind-variants cover the same concepts in more detail.