I just shipped Varwolf v1.0 - a lightweight library (2KB gzipped!) that lets you control CSS variables dynamically with pseudo-classes like :hover
, :focus
, and :active
in React.
๐ก The Problem
Ever tried to make a CSS variable change on hover?
// โ This doesn't work
<div
style={{
'--color': 'red',
backgroundColor: 'var(--color)'
}}
onMouseEnter={() => /* how to change --color? */}
/>
You'd need state management, event handlers, and lots of boilerplate just to change one variable on hover.
โจ The Solution
import { varwolf } from "varwolf"
<varwolf.button
style={{
__bg: "red",
backgroundColor: "var(--bg)",
_hover: {
__bg: "blue"
}
}}
>
Hover me!
</varwolf.button>
The __
prefix creates CSS variables, and _hover
makes them change on hover. Pure CSS, no JavaScript!
๐ Key Features
1. Pseudo-Classes with Underscore Prefix
Use camelCase with _
prefix for any pseudo-class:
<varwolf.div
style={{
__opacity: 1,
opacity: "var(--opacity)",
_hover: { __opacity: 0.8 },
_active: { __opacity: 0.6 },
_focus: { __opacity: 0.9 },
_disabled: { __opacity: 0.3 }
}}
/>
2. Nested Selectors
Combine multiple states:
<varwolf.button
style={{
__color: "black",
_hover: {
__color: "blue",
_disabled: {
__color: "gray" // :hover:disabled
}
}
}}
/>
3. currentValue Functions
Modify existing values instead of replacing:
<varwolf.div
style={{
__size: "100px",
width: "var(--size)",
_hover: {
__size: (currentValue) => `calc(${currentValue} * 1.2)`
}
}}
/>
4. Cross-State References
Reference values from other pseudo-states:
<varwolf.button
style={{
__bg: "red",
_hover: { __bg: "blue" },
_active: {
__bg: (cv, from = "hover") => cv // Use hover's value
}
}}
/>
5. Hybrid Rendering
Combine CSS variables with dynamic inline styles:
const [scrollY, setScrollY] = useState(0)
<varwolf.div
style={{
__bg: "red",
_hover: { __bg: "blue" }
}}
inlineStyle={{
transform: `translateY(${scrollY}px)`
}}
/>
๐ Why Varwolf?
Size Comparison
Format | Size | Description |
---|---|---|
Package (.tgz) | 19.4 KB | Includes TypeScript types |
Minified | ~8 KB | Production JavaScript |
Gzipped | ~2 KB | Actual download size โ |
vs Competition
Library | Gzipped | vs Varwolf |
---|---|---|
styled-components | 15.2 KB | 8.4x larger |
Emotion | 8.9 KB | 4.9x larger |
Stitches | 5.8 KB | 3.2x larger |
vanilla-extract | 4.2 KB | 2.3x larger |
Varwolf | 1.8 KB | Winner! ๐ |
๐ป Real-World Example
Here's an animated button with hover, active, and disabled states:
import { varwolf } from "varwolf"
import { useState } from "react"
function AnimatedButton() {
const [loading, setLoading] = useState(false)
return (
<varwolf.button
style={{
__bg: "blue",
__scale: "1",
backgroundColor: "var(--bg)",
transform: "scale(var(--scale))",
padding: "10px 20px",
border: "none",
color: "white",
cursor: "pointer",
transition: "all 0.3s ease",
_hover: {
__bg: "darkblue",
__scale: "1.05"
},
_active: {
__scale: "0.95"
},
_disabled: {
__bg: "gray",
cursor: "not-allowed"
}
}}
disabled={loading}
onClick={() => setLoading(true)}
>
{loading ? "Loading..." : "Click me!"}
</varwolf.button>
)
}
๐ง How It Works
Varwolf injects CSS rules into a <style>
tag:
.varwolf-abc123 {
--bg: red;
}
.varwolf-abc123:hover {
--bg: blue;
}
Your component gets the class name, and CSS variables update on interaction. No JavaScript event handlers needed!
๐ฆ Installation
npm install varwolf
โก Features at a Glance
- โ 2KB gzipped - Smallest CSS-in-JS library
- โ Zero dependencies - No bloat
- โ TypeScript - Full type safety
- โ
Pseudo-classes -
:hover
,:focus
,:active
, etc. - โ
Nested selectors -
:hover:disabled
- โ
Dynamic values -
currentValue
functions - โ Cross-state refs - Reference other states
- โ Performance optimized - Smart caching & hashing
๐ฏ Use Cases
Theme Switching
<varwolf.div
style={{
__theme: darkMode ? "dark" : "light",
__bg: "white",
__color: "black",
'[data-theme="dark"]': {
__bg: "black",
__color: "white"
}
}}
/>
Loading States
<varwolf.button
style={{
__opacity: 1,
opacity: "var(--opacity)",
'[aria-busy="true"]': {
__opacity: 0.5
}
}}
/>
Responsive Hover Effects
<varwolf.card
style={{
__elevation: "2px",
boxShadow: "0 var(--elevation) 10px rgba(0,0,0,0.1)",
_hover: {
__elevation: "8px"
}
}}
/>
๐ฎ What's Next?
Planned features for future releases:
- Media query support (
_md
,_lg
) - Animation helpers
- Theme presets
- Container queries
- More pseudo-classes
๐ฌ Feedback Welcome!
This is v1.0, and I'd love your thoughts:
- What features would you add?
- How can the API be improved?
- Found any bugs?
Drop a comment or open an issue on GitHub!
๐ Links
- ๐ฆ npm package
- ๐ GitHub repository
- ๐ Full documentation
๐ Thanks!
If you find varwolf useful:
- โญ Star it on GitHub
- ๐ฌ Share your feedback
- ๐ Report bugs
- ๐ Try it in your project
Built with ๐บ by Kunal Tanwar
Have you tried CSS variables in React? What challenges have you faced? Let me know in the comments! ๐
Top comments (0)