Performance
css-variants is designed to be fast and lightweight. Here’s what you need to know about performance.
Bundle Size
Section titled “Bundle Size”css-variants is extremely lightweight:
- Core library: ~1KB minified + gzipped
- Zero dependencies: No additional packages bundled
- Tree-shakeable: Import only what you need
Selective Imports
Section titled “Selective Imports”Each function can be imported independently:
// Only imports cv (~400 bytes)import { cv } from 'css-variants/cv'
// Only imports scv (~600 bytes)import { scv } from 'css-variants/scv'
// Only imports cx (~200 bytes)import { cx } from 'css-variants/scv'
// Import multipleimport { cv, cx } from 'css-variants'Runtime Performance
Section titled “Runtime Performance”Variant Creation
Section titled “Variant Creation”Variant functions are created once and reused:
// ✅ Good: Created once at module levelconst button = cv({ base: 'rounded font-medium', variants: { /* ... */ },})
function Button(props) { return <button className={button(props)} />}// ❌ Bad: Recreated on every renderfunction Button(props) { const button = cv({ base: 'rounded font-medium', variants: { /* ... */ }, }) return <button className={button(props)} />}Variant Resolution
Section titled “Variant Resolution”When you call a variant function:
- Base classes are concatenated (O(1))
- Selected variants are looked up by key (O(1) per variant)
- Compound variants are checked (O(n) where n = number of compound rules)
- Classes are merged using cx (O(m) where m = total classes)
For typical usage with 3-5 variants and 2-3 compound rules, this is extremely fast.
Optimization Tips
Section titled “Optimization Tips”1. Minimize Compound Variants
Section titled “1. Minimize Compound Variants”Each compound variant is checked at runtime:
// More compound variants = more checkscompoundVariants: [ { size: 'lg', color: 'primary', className: '...' }, { size: 'lg', color: 'secondary', className: '...' }, { size: 'md', color: 'primary', className: '...' }, // ... many more]Consider restructuring if you have many compound variants:
// Better: Use a dedicated variant insteadvariants: { featured: { true: 'shadow-lg font-bold', false: '', },}2. Avoid Dynamic Variant Creation
Section titled “2. Avoid Dynamic Variant Creation”// ❌ Bad: Creates new variant on each callfunction getButtonVariant(theme: 'light' | 'dark') { return cv({ base: theme === 'dark' ? 'bg-gray-800' : 'bg-white', variants: { /* ... */ }, })}// ✅ Good: Handle themes within variantsconst button = cv({ variants: { theme: { light: 'bg-white text-gray-900', dark: 'bg-gray-800 text-white', }, // ... other variants },})3. Use Slot Variants Appropriately
Section titled “3. Use Slot Variants Appropriately”scv creates an object of class strings for each slot. Only use it when you have multiple related elements:
// ✅ Good: Multiple related elementsconst card = scv({ slots: ['root', 'header', 'content', 'footer'], // ...})
// ❌ Overkill: Single elementconst button = scv({ slots: ['root'], // Just use cv() instead // ...})4. Memoization (React)
Section titled “4. Memoization (React)”For components that render frequently with the same props, consider memoization:
import { useMemo } from 'react'
function ExpensiveComponent({ color, size, ...props }) { const className = useMemo( () => button({ color, size }), [color, size] )
return <button className={className} {...props} />}However, for most cases this is unnecessary - variant resolution is fast enough.
Memory Usage
Section titled “Memory Usage”Variant definitions are plain JavaScript objects and have minimal memory overhead. The main memory considerations:
- Variant configuration: Stored once per variant definition
- Generated classes: New strings created per call (garbage collected normally)
- Compound variant arrays: One array per variant definition
For typical applications with dozens of component variants, memory usage is negligible.
Server-Side Rendering
Section titled “Server-Side Rendering”css-variants works identically on server and client:
- No DOM dependencies
- No browser-specific APIs
- Same output in Node.js and browser
This makes it ideal for SSR frameworks like Next.js, Nuxt, and Remix.
Production Tips Summary
Section titled “Production Tips Summary”- Create variants at module level, not inside components
- Keep compound variants minimal
- Use
cvfor single elements,scvfor multi-element components - Import only what you need for optimal tree-shaking
- Memoize only when profiling shows it’s needed
Benchmark Comparison
Section titled “Benchmark Comparison”css-variants delivers exceptional performance compared to popular alternatives:
| Benchmark | vs cva | vs tailwind-variants |
|---|---|---|
| Overall | ⚡ Faster in 11/13 scenarios | ⚡ Faster in all scenarios |
| Compound Variants | 🚀 3-4x faster | 🚀 5-6x faster |
| Complex Components | 🚀 4-9x faster | 🚀 10-11x faster |
| Simple Operations | ✓ Competitive | 🚀 3-7x faster |
Benchmarks last updated: 2025-12-11
Run yarn bench:cva and yarn bench:tailwind-variants to regenerate these benchmarks on your machine.
Benchmark source code: