Introduction
Vanilla Extract is a CSS authoring framework that lets you write styles in TypeScript files (.css.ts) and compiles them to static CSS at build time. You get full type safety, autocomplete, and theming capabilities without shipping any CSS runtime to the browser.
What Vanilla Extract Does
- Generates static CSS files from TypeScript style definitions at build time
- Provides type-safe APIs for styles, themes, and design tokens
- Supports theming via CSS custom properties with contract-based type checking
- Offers a Sprinkles utility for building type-safe atomic CSS functions
- Integrates with Vite, Webpack, esbuild, and Next.js via official plugins
Architecture Overview
Style files (.css.ts) are evaluated at build time by a bundler plugin. The plugin extracts all style(), globalStyle(), and createTheme() calls, generates corresponding CSS, and replaces the TypeScript exports with hashed class name strings. The output is plain CSS with no runtime JavaScript, so the styles have zero impact on client bundle size.
Self-Hosting & Configuration
- Install
@vanilla-extract/cssand the plugin for your bundler (e.g.,@vanilla-extract/vite-plugin) - Add the plugin to your build configuration (Vite, Webpack, or esbuild)
- Create
.css.tsfiles alongside your components for co-located styling - Define themes with
createTheme()andcreateThemeContract()for type-safe design tokens - Use
@vanilla-extract/sprinklesto create utility-class functions like a typed Tailwind
Key Features
- Full TypeScript autocomplete and compile-time error checking for all style properties
- Zero runtime cost since all CSS is extracted at build time
- Theme contracts that enforce consistent token usage across themes
- Recipes API for building variant-based component styles (similar to CVA)
- Locally scoped class names by default to prevent style collisions
Comparison with Similar Tools
- CSS Modules — Also locally scoped, but no type safety or theming primitives
- Tailwind CSS — Utility-first approach; Vanilla Extract provides type-safe authoring in TS
- Styled Components / Emotion — Runtime CSS-in-JS with bundle cost; Vanilla Extract has zero runtime
- Linaria — Similar zero-runtime goal; Vanilla Extract has a richer theming and Sprinkles API
- Panda CSS — Newer utility-first zero-runtime library; Vanilla Extract is more established
FAQ
Q: Does Vanilla Extract work with Next.js?
A: Yes. Use the @vanilla-extract/next-plugin to add support to your Next.js project.
Q: Can I use media queries and pseudo-selectors?
A: Yes. Nest them inside the style() call using keys like @media, :hover, and :focus.
Q: How does theming work?
A: Define a theme contract with createThemeContract(), then create concrete themes with createTheme(). Components reference contract variables and the active theme is applied via a class on a parent element.
Q: Is there a performance benefit over runtime CSS-in-JS? A: Yes. Since all CSS is pre-generated, there is no style injection or serialization at runtime, reducing JavaScript execution and improving time-to-interactive.