Vanilla Extract generates zero-runtime CSS from TypeScript at build time. You get full type safety for your styles without any runtime cost.
The Free APIs You're Missing
1. Sprinkles — Atomic CSS with Type Safety
// sprinkles.css.ts
import { defineProperties, createSprinkles } from "@vanilla-extract/sprinkles";
const responsiveProperties = defineProperties({
conditions: {
mobile: {},
tablet: { "@media": "(min-width: 768px)" },
desktop: { "@media": "(min-width: 1024px)" },
},
defaultCondition: "mobile",
properties: {
display: ["none", "flex", "grid", "block"],
flexDirection: ["row", "column"],
gap: { 0: 0, 1: "4px", 2: "8px", 3: "16px", 4: "24px" },
padding: { 0: 0, 1: "4px", 2: "8px", 3: "16px", 4: "24px" },
},
});
export const sprinkles = createSprinkles(responsiveProperties);
// Usage: className={sprinkles({ display: { mobile: "block", desktop: "flex" }, gap: 3 })}
Tailwind-like atomic CSS with full TypeScript autocomplete. Invalid values are compile errors.
2. Recipes — Component Variant API
import { recipe } from "@vanilla-extract/recipes";
export const button = recipe({
base: {
borderRadius: 8,
fontWeight: 600,
border: "none",
cursor: "pointer",
transition: "all 0.2s",
},
variants: {
color: {
primary: { background: "#3b82f6", color: "white" },
secondary: { background: "#6b7280", color: "white" },
danger: { background: "#ef4444", color: "white" },
},
size: {
sm: { padding: "6px 12px", fontSize: 14 },
md: { padding: "8px 16px", fontSize: 16 },
lg: { padding: "12px 24px", fontSize: 18 },
},
},
compoundVariants: [
{ variants: { color: "primary", size: "lg" }, style: { boxShadow: "0 4px 12px rgba(59,130,246,0.4)" } },
],
defaultVariants: { color: "primary", size: "md" },
});
// <button className={button({ color: "danger", size: "lg" })}>
3. createTheme() — Type-Safe Theming
import { createTheme, createThemeContract } from "@vanilla-extract/css";
const vars = createThemeContract({
color: { brand: null, text: null, bg: null },
space: { sm: null, md: null, lg: null },
});
export const lightTheme = createTheme(vars, {
color: { brand: "#3b82f6", text: "#1a1a1a", bg: "#ffffff" },
space: { sm: "4px", md: "8px", lg: "16px" },
});
export const darkTheme = createTheme(vars, {
color: { brand: "#60a5fa", text: "#f5f5f5", bg: "#0a0a0a" },
space: { sm: "4px", md: "8px", lg: "16px" },
});
// Use: style({ color: vars.color.text }) — works in both themes
4. Dynamic Styles — CSS Variables at Runtime
import { createVar, style, assignInlineVars } from "@vanilla-extract/css";
const progressVar = createVar();
export const progressBar = style({
width: progressVar,
height: 8,
background: "#3b82f6",
borderRadius: 4,
transition: "width 0.3s",
});
// React: <div className={progressBar} style={assignInlineVars({ [progressVar]: `${progress}%` })} />
5. globalStyle() — Scoped Global Styles
import { globalStyle } from "@vanilla-extract/css";
globalStyle("html, body", {
margin: 0,
fontFamily: "system-ui, sans-serif",
});
globalStyle(`${container} > a`, {
color: vars.color.brand,
textDecoration: "none",
});
Getting Started
npm install @vanilla-extract/css @vanilla-extract/vite-plugin
Need data from any website delivered as clean JSON? I build production web scrapers that handle anti-bot, proxies, and rate limits. 77 scrapers running in production. Email me: Spinov001@gmail.com
Check out my awesome-web-scraping list for the best scraping tools and resources.
Top comments (0)