
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
css-variants
Advanced tools
Lightweight helpers to compose class names and inline styles using variants. Zero runtime deps, small bundle, and first-class TypeScript support.
Fastest CSS variant library for JavaScript and TypeScript
Type-safe alternative to CVA (Class Variance Authority) and tailwind-variants. ~1KB gzipped. 3-11x faster. Zero dependencies.
css-variants is a JavaScript library for managing CSS class variants with full TypeScript support. Define style variations (color, size, state) declaratively and get the correct CSS classes at runtime.
Works with Tailwind CSS, vanilla CSS, CSS Modules, or any styling solution.
npm install css-variants
pnpm add css-variants
yarn add css-variants
Create type-safe variants for single-element components:
import { cv } from 'css-variants'
const button = cv({
base: 'font-semibold rounded-lg transition-colors',
variants: {
color: {
primary: 'bg-blue-600 text-white hover:bg-blue-700',
secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
},
size: {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 py-2 text-base',
lg: 'px-6 py-3 text-lg',
},
},
defaultVariants: {
color: 'primary',
size: 'md',
},
})
button() // Uses defaults
button({ color: 'secondary', size: 'lg' }) // Override variants
button({ className: 'w-full' }) // Add custom classes
Create variants for multi-element components (cards, modals, dropdowns):
import { scv } from 'css-variants'
const card = scv({
slots: ['root', 'header', 'body', 'footer'],
base: {
root: 'rounded-xl border shadow-sm',
header: 'px-6 py-4 border-b font-semibold',
body: 'px-6 py-4',
footer: 'px-6 py-3 bg-gray-50',
},
variants: {
variant: {
default: { root: 'bg-white border-gray-200' },
primary: { root: 'bg-blue-50 border-blue-200' },
},
},
})
const classes = card({ variant: 'primary' })
// classes.root → 'rounded-xl border shadow-sm bg-blue-50 border-blue-200'
// classes.header → 'px-6 py-4 border-b font-semibold'
Create variants that return CSS style objects:
import { sv } from 'css-variants'
const box = sv({
base: { display: 'flex', borderRadius: '8px' },
variants: {
size: {
sm: { padding: '8px' },
lg: { padding: '24px' },
},
},
})
<div style={box({ size: 'lg' })} />
Lightweight clsx alternative for conditional class merging:
import { cx } from 'css-variants'
cx('btn', 'btn-primary') // 'btn btn-primary'
cx('btn', isActive && 'active') // 'btn active' or 'btn'
cx('btn', { disabled: isDisabled }) // 'btn disabled' or 'btn'
| Feature | css-variants | CVA | tailwind-variants |
|---|---|---|---|
| Bundle size | ~1KB | ~2KB | ~5KB |
| Performance | Baseline | 3-7x slower | 5-11x slower |
| Slot variants | Built-in | No | Yes |
| Style variants | Built-in | No | No |
| Dependencies | 0 | 1 | 1 |
Use with tailwind-merge for class conflict resolution:
import { cv, cx } from 'css-variants'
import { twMerge } from 'tailwind-merge'
const button = cv({
base: 'px-4 py-2 rounded',
variants: {
size: { lg: 'px-6 py-3' },
},
classNameResolver: (...args) => twMerge(cx(...args)),
})
import { cv } from 'css-variants'
const button = cv({
base: 'rounded font-medium',
variants: {
variant: { primary: 'bg-blue-600 text-white' },
},
})
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
Parameters<typeof button>[0]
function Button({ variant, className, ...props }: ButtonProps) {
return <button className={button({ variant, className })} {...props} />
}
<script setup lang="ts">
import { cv } from 'css-variants'
const button = cv({
base: 'rounded font-medium',
variants: {
variant: { primary: 'bg-blue-600 text-white' },
},
})
defineProps<{ variant?: 'primary' }>()
</script>
<template>
<button :class="button({ variant })"><slot /></button>
</template>
- import { cva } from 'class-variance-authority'
+ import { cv } from 'css-variants'
- const button = cva('base-classes', {
+ const button = cv({
+ base: 'base-classes',
variants: { /* same */ },
compoundVariants: [
- { color: 'primary', class: 'extra' }
+ { color: 'primary', className: 'extra' }
],
})
| Function | Description |
|---|---|
cv() | Class variants for single-element components |
scv() | Slot class variants for multi-element components |
sv() | Style variants for inline CSS style objects |
ssv() | Slot style variants for multi-element inline styles |
cx() | Class merger utility (like clsx) |
MIT © Tim Phan
FAQs
Lightweight helpers to compose class names and inline styles using variants. Zero runtime deps, small bundle, and first-class TypeScript support.
The npm package css-variants receives a total of 4,265 weekly downloads. As such, css-variants popularity was classified as popular.
We found that css-variants demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.