This content originally appeared on DEV Community and was authored by Kunal Tanwar
Introducing Varkit
I’m excited to share my first open-source library: Varkit – a lightweight solution for managing CSS variables in React with full TypeScript support!
The Problem
While building React applications, I kept running into the same frustrations with styling:
- Prop drilling for theme values – Passing colors and sizes through multiple components
-
Separate CSS files for pseudo-classes –
:hover
,:focus
states living far from component logic - No type safety – Typos in CSS variable names only caught at runtime
- Heavy CSS-in-JS libraries – 15KB+ just for styling
I wanted something lightweight, type-safe, and intuitive. That’s why I built Varkit.
What is Varkit?
Varkit is a 6.4KB library that lets you define and manipulate CSS variables directly in React components with full TypeScript support.
Key Features:
CSS variables with
__
prefix – Clean, intuitive syntaxPseudo-class support with
_
prefix –:hover
,:focus
,:active
, and 50+ moreFunction-based dynamic values – Compute values on the fly
Zero dependencies – Minimal bundle impact
Full TypeScript support – Catch errors before runtime
Works with all HTML elements – Via Proxy magic
Installation
npm install @kunaltanwar/varkit
# or
pnpm add @kunaltanwar/varkit
# or
yarn add @kunaltanwar/varkit
Quick Start
Here’s a simple button with hover effects:
import { varkit } from '@kunaltanwar/varkit'
function App() {
return (
<varkit.button
style={{
// Define CSS variables
__bg: 'blue',
__color: 'white',
__padding: '12px 24px',
// Use them in regular CSS
backgroundColor: 'var(--bg)',
color: 'var(--color)',
padding: 'var(--padding)',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
fontSize: '16px',
// Pseudo-classes
_hover: {
__bg: 'darkblue',
transform: 'scale(1.05)',
},
_active: {
__bg: 'navy',
},
}}
>
Click Me!
</varkit.button>
)
}
That’s it! No separate CSS files, no complex setup.
Real-World Examples
1. Theme Switcher
function Card({ theme = 'light' }) {
const themes = {
light: { bg: '#fff', text: '#000', border: '#ddd' },
dark: { bg: '#222', text: '#fff', border: '#555' },
}
const { bg, text, border } = themes[theme]
return (
<varkit.div
style={{
__bg: bg,
__text: text,
__border: border,
backgroundColor: 'var(--bg)',
color: 'var(--text)',
border: '1px solid var(--border)',
padding: '20px',
borderRadius: '8px',
transition: 'all 0.3s',
}}
>
<h2>Themed Card</h2>
<p>Switch between light and dark mode!</p>
</varkit.div>
)
}
2. Interactive Form Input
function Input({ error }) {
return (
<varkit.input
style={{
__borderColor: error ? 'red' : '#ccc',
__focusColor: error ? 'darkred' : 'blue',
border: '2px solid var(--border-color)',
padding: '10px',
borderRadius: '4px',
outline: 'none',
transition: 'all 0.2s',
_focus: {
__borderColor: 'var(--focus-color)',
boxShadow: '0 0 0 3px rgba(0,0,255,0.1)',
},
}}
/>
)
}
3. Animated Card (with Function-Based Values)
function AnimatedCard() {
return (
<varkit.div
style={{
__scale: 1,
__rotate: '0deg',
width: '200px',
height: '200px',
backgroundColor: '#4CAF50',
transform: 'scale(var(--scale)) rotate(var(--rotate))',
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
_hover: {
__scale: 1.1,
__rotate: '5deg',
boxShadow: '0 10px 40px rgba(0,0,0,0.2)',
},
}}
>
<p>Hover me!</p>
</varkit.div>
)
}
How It Works
Varkit uses a clever approach:
-
Parses your style object – Identifies CSS variables (
__prefix
) and pseudo-classes (_prefix
) - Generates CSS rules – Converts to standard CSS with proper selectors
-
Injects styles – Adds a
<style id="varkit">
tag to the document - Deduplicates – Uses hash-based caching to avoid redundant CSS
Example transformation:
<varkit.div style={{ __bg: 'red' }}>Content</varkit.div>
Becomes:
<div data-vk="vk-abc123">Content</div>
<style id="varkit">
[data-vk="vk-abc123"] {
--bg: red;
}
</style>
Why Choose Varkit?
vs Styled-Components
Feature | Varkit | Styled-Components |
---|---|---|
Size | 6.4 KB | 15+ KB |
Runtime | Minimal | Heavy |
CSS Variables | ![]() |
![]() |
Learning Curve | Easy | Moderate |
TypeScript | ![]() |
![]() |
vs Emotion
Feature | Varkit | Emotion |
---|---|---|
Size | 6.4 KB | 10+ KB |
Syntax | Inline styles | CSS strings |
CSS Variables | ![]() |
![]() |
Setup | None | Config needed |
vs Vanilla CSS
Feature | Varkit | Vanilla CSS |
---|---|---|
Colocation | ![]() |
![]() |
Dynamic | ![]() |
![]() |
Type-safe | ![]() |
![]() |
Maintenance | ![]() |
![]() |
Advanced Features
Supported Pseudo-Classes
Varkit supports 50+ pseudo-classes:
-
Interactive:
:hover
,:focus
,:active
,:disabled
-
Form states:
:checked
,:invalid
,:valid
,:required
-
Structural:
:first-child
,:last-child
,:only-child
-
Text:
:empty
,:read-only
,:read-write
- And many more!
TypeScript Support
Full type safety out of the box:
import { varkit, VarkitProps, VarkitStyles } from '@kunaltanwar/varkit'
// Type-safe styles
const styles: VarkitStyles = {
__bg: 'red',
_hover: {
__bg: 'blue', // ✅ Type-checked
},
}
// Type-safe component props
type ButtonProps = VarkitProps<'button'> & {
variant: 'primary' | 'secondary'
}
Performance
Varkit is designed for performance:
Automatic deduplication – Same styles = one CSS rule
Hash-based caching – Rules injected only once
Minimal overhead – Just string manipulation
No runtime CSS parsing – Pre-computed at render
Bundle impact: Only 6.4 KB gzipped!
Roadmap
I’m actively working on:
v1.1
- Functional pseudo-classes (
:nth-child
,:has
,:not
) - Animation keyframes support
- Media query support
- Container queries
v1.2
- Server-side rendering (SSR)
- Next.js App Router compatibility
- Theme provider component
- CSS extraction for production
v2.0 (Maybe)
- Babel plugin for optimizations
- VS Code extension
- Migration tools from styled-components/Emotion
Get Started Today!
npm install @kunaltanwar/varkit
Links:
Contributing
Varkit is open-source and contributions are welcome!
Star the repo if you find it useful
Report bugs and suggest features
Submit pull requests
Improve documentation
Join discussions
Final Thoughts
Building Varkit taught me a lot about:
- React internals and Proxies
- TypeScript library design
- CSS variable manipulation
- npm package publishing
- Open-source best practices
I hope it solves styling challenges for you too!
Try it out and let me know what you think! Feedback is always welcome.
If you found this helpful, please give it a and share with your React developer friends!
This content originally appeared on DEV Community and was authored by Kunal Tanwar