Vanilla Extract is a zero-runtime CSS-in-TypeScript framework. Write styles in .css.ts files, get static CSS with full type safety.
Basic Styles
// styles.css.ts
import { style, globalStyle } from "@vanilla-extract/css";
export const container = style({
maxWidth: "1200px",
margin: "0 auto",
padding: "24px",
});
export const card = style({
background: "white",
borderRadius: "12px",
padding: "24px",
boxShadow: "0 4px 6px rgba(0,0,0,0.1)",
":hover": {
boxShadow: "0 10px 20px rgba(0,0,0,0.15)",
transform: "translateY(-2px)",
},
"@media": {
"(max-width: 768px)": {
padding: "16px",
},
},
});
// Usage
import { container, card } from "./styles.css";
<div className={container}><div className={card}>Content</div></div>
Sprinkles: Atomic CSS API
// 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", "block", "grid"],
flexDirection: ["row", "column"],
gap: { 0: "0", 1: "4px", 2: "8px", 3: "12px", 4: "16px", 6: "24px", 8: "32px" },
padding: { 0: "0", 1: "4px", 2: "8px", 3: "12px", 4: "16px", 6: "24px" },
fontSize: { sm: "14px", md: "16px", lg: "20px", xl: "24px" },
},
});
const colorProperties = defineProperties({
conditions: { light: {}, dark: { "@media": "(prefers-color-scheme: dark)" } },
defaultCondition: "light",
properties: {
color: { primary: "#3b82f6", secondary: "#64748b", text: "#1e293b" },
background: { surface: "white", muted: "#f1f5f9", dark: "#0f172a" },
},
});
export const sprinkles = createSprinkles(responsiveProperties, colorProperties);
// Usage — fully type-safe!
const className = sprinkles({
display: { mobile: "block", desktop: "flex" },
gap: 4,
padding: 6,
color: "primary",
});
Recipes: Component Variants
import { recipe } from "@vanilla-extract/recipes";
export const button = recipe({
base: {
borderRadius: "8px",
fontWeight: 600,
cursor: "pointer",
transition: "all 0.2s",
},
variants: {
color: {
primary: { background: "#3b82f6", color: "white" },
danger: { background: "#ef4444", color: "white" },
},
size: {
sm: { padding: "8px 16px", fontSize: "14px" },
md: { padding: "12px 24px", fontSize: "16px" },
lg: { padding: "16px 32px", fontSize: "18px" },
},
},
defaultVariants: { color: "primary", size: "md" },
});
// Usage
<button className={button({ color: "danger", size: "lg" })}>Delete</button>
Theme API
import { createTheme, createThemeContract } from "@vanilla-extract/css";
const vars = createThemeContract({
color: { brand: null, text: null, surface: null },
space: { sm: null, md: null, lg: null },
});
export const lightTheme = createTheme(vars, {
color: { brand: "#3b82f6", text: "#1e293b", surface: "#ffffff" },
space: { sm: "8px", md: "16px", lg: "32px" },
});
export const darkTheme = createTheme(vars, {
color: { brand: "#60a5fa", text: "#f1f5f9", surface: "#0f172a" },
space: { sm: "8px", md: "16px", lg: "32px" },
});
Type-safe styling for data apps? My Apify tools power the data layer.
Custom solution? Email spinov001@gmail.com
Top comments (1)
1642 posts in 11 days seem to be a bit excessive. I hope you aren't a bot. This duplicate content is absolutely flooding the RSS feed.