Convert Figma logo to code with AI

vanilla-extract-css logovanilla-extract

Zero-runtime Stylesheets-in-TypeScript

9,496
286
9,496
68

Top Related Projects

Documentation about css-modules

Visual primitives for the component age. Use the best bits of ES6 and CSS to style your apps without stress 💅

17,457

👩‍🎤 CSS-in-JS library designed for high performance style composition

A utility-first CSS framework for rapid UI development.

11,639

Zero-runtime CSS in JS library

Quick Overview

Vanilla Extract is a zero-runtime CSS-in-TypeScript library that generates static CSS files during build time. It provides a type-safe way to author styles using TypeScript, offering features like theming, dynamic sprinkles, and CSS modules, all while maintaining the benefits of traditional CSS.

Pros

  • Type-safe CSS authoring with TypeScript
  • Zero runtime overhead, as styles are generated at build time
  • Supports theming and dynamic styles without sacrificing performance
  • Integrates well with existing CSS ecosystems and tooling

Cons

  • Requires a build step, which may increase complexity in some projects
  • Learning curve for developers used to traditional CSS or other CSS-in-JS solutions
  • Limited runtime style manipulation compared to some other CSS-in-JS libraries
  • Relatively new project, so the ecosystem and community support are still growing

Code Examples

Creating a simple style:

import { style } from '@vanilla-extract/css';

export const container = style({
  padding: '20px',
  backgroundColor: '#f0f0f0',
});

Defining a theme:

import { createTheme } from '@vanilla-extract/css';

export const [themeClass, vars] = createTheme({
  color: {
    primary: '#007bff',
    secondary: '#6c757d',
  },
  font: {
    body: 'Arial, sans-serif',
  },
});

Using sprinkles for responsive styles:

import { defineProperties, createSprinkles } from '@vanilla-extract/sprinkles';

const responsiveProperties = defineProperties({
  conditions: {
    mobile: {},
    tablet: { '@media': 'screen and (min-width: 768px)' },
    desktop: { '@media': 'screen and (min-width: 1024px)' },
  },
  defaultCondition: 'mobile',
  properties: {
    display: ['none', 'flex', 'block', 'inline'],
    flexDirection: ['row', 'column'],
    padding: ['0', '4px', '8px', '16px', '32px'],
  },
});

export const sprinkles = createSprinkles(responsiveProperties);

Getting Started

  1. Install Vanilla Extract:

    npm install @vanilla-extract/css
    
  2. Set up your build tool (e.g., webpack, Vite) with the Vanilla Extract plugin.

  3. Create a CSS file with a .css.ts extension:

    // styles.css.ts
    import { style } from '@vanilla-extract/css';
    
    export const myStyle = style({
      color: 'blue',
      fontSize: '16px',
    });
    
  4. Use the generated class in your component:

    import { myStyle } from './styles.css';
    
    function MyComponent() {
      return <div className={myStyle}>Hello, Vanilla Extract!</div>;
    }
    

Competitor Comparisons

Documentation about css-modules

Pros of CSS Modules

  • Simpler setup and integration with existing CSS workflows
  • Wider adoption and community support
  • Works with any CSS preprocessor (SASS, LESS, etc.)

Cons of CSS Modules

  • Limited type safety and static analysis
  • Requires additional tooling for full CSS-in-JS capabilities
  • Less flexibility in dynamic styling and theme generation

Code Comparison

CSS Modules:

.button {
  background-color: blue;
  color: white;
}
import styles from './Button.css';

const Button = () => <button className={styles.button}>Click me</button>;

Vanilla Extract:

import { style } from '@vanilla-extract/css';

export const button = style({
  backgroundColor: 'blue',
  color: 'white'
});
import { button } from './Button.css.ts';

const Button = () => <button className={button}>Click me</button>;

CSS Modules offers a more familiar approach for developers accustomed to traditional CSS, while Vanilla Extract provides stronger typing and a more JavaScript-centric workflow. CSS Modules is easier to adopt in existing projects, but Vanilla Extract offers better performance and more advanced features for complex styling needs.

Visual primitives for the component age. Use the best bits of ES6 and CSS to style your apps without stress 💅

Pros of styled-components

  • Dynamic styling with JavaScript: Allows for more complex and conditional styles
  • Better developer experience with syntax highlighting and auto-completion
  • Automatic critical CSS extraction for improved performance

Cons of styled-components

  • Runtime overhead: Styles are generated and injected at runtime
  • Larger bundle size due to the library itself and generated styles
  • Potential for prop pollution and overuse of the styled API

Code Comparison

styled-components:

const Button = styled.button`
  background-color: ${props => props.primary ? 'blue' : 'white'};
  color: ${props => props.primary ? 'white' : 'blue'};
  padding: 10px 20px;
`;

vanilla-extract:

import { style, styleVariants } from '@vanilla-extract/css';

const baseButton = style({
  padding: '10px 20px',
});

export const button = styleVariants({
  primary: [baseButton, { backgroundColor: 'blue', color: 'white' }],
  secondary: [baseButton, { backgroundColor: 'white', color: 'blue' }],
});

Both libraries offer component-based styling solutions, but vanilla-extract generates styles at build time, resulting in zero runtime cost and type-safe CSS. styled-components provides a more familiar CSS-in-JS experience with dynamic styling capabilities at the cost of runtime performance.

17,457

👩‍🎤 CSS-in-JS library designed for high performance style composition

Pros of emotion

  • Runtime CSS-in-JS allows for dynamic styling based on props and state
  • Extensive ecosystem with additional libraries and integrations
  • Supports server-side rendering out of the box

Cons of emotion

  • Runtime performance overhead due to style injection
  • Larger bundle size compared to static CSS solutions
  • Potential for style conflicts in global scope

Code Comparison

emotion:

import { css } from '@emotion/react'

const style = css`
  color: hotpink;
`

const SomeComponent = ({ children }) => (
  <div css={style}>{children}</div>
)

vanilla-extract:

import { style } from '@vanilla-extract/css'

const myStyle = style({
  color: 'hotpink'
})

const SomeComponent = ({ children }) => (
  <div className={myStyle}>{children}</div>
)

vanilla-extract generates static CSS at build time, resulting in smaller bundle sizes and better runtime performance. It also provides type safety for styles and class names. However, it lacks the dynamic capabilities of emotion and requires additional setup for server-side rendering.

emotion offers more flexibility for runtime styling and has a larger ecosystem, but comes with performance trade-offs and potential style conflicts. The choice between the two depends on project requirements, performance needs, and developer preferences.

A utility-first CSS framework for rapid UI development.

Pros of Tailwind CSS

  • Rapid prototyping and development with utility-first approach
  • Extensive pre-built classes for common design patterns
  • Large community and ecosystem with numerous resources and plugins

Cons of Tailwind CSS

  • Steeper learning curve for developers new to utility-first CSS
  • Potential for larger HTML files due to multiple class names
  • Less type-safe compared to Vanilla Extract's TypeScript integration

Code Comparison

Tailwind CSS:

<div class="bg-blue-500 text-white p-4 rounded-lg shadow-md">
  <h3 class="text-xl font-bold mb-2">Hello, Tailwind!</h3>
  <p class="text-sm">This is a sample component.</p>
</div>

Vanilla Extract:

import { style } from '@vanilla-extract/css';

const container = style({
  backgroundColor: 'blue',
  color: 'white',
  padding: '1rem',
  borderRadius: '0.5rem',
  boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)'
});

const heading = style({
  fontSize: '1.25rem',
  fontWeight: 'bold',
  marginBottom: '0.5rem'
});

const paragraph = style({
  fontSize: '0.875rem'
});
11,639

Zero-runtime CSS in JS library

Pros of Linaria

  • Zero runtime CSS-in-JS with no style injection
  • Supports dynamic styles with CSS variables
  • Works with server-side rendering out of the box

Cons of Linaria

  • Requires additional build step and configuration
  • Limited TypeScript support compared to Vanilla Extract
  • Less robust theming capabilities

Code Comparison

Linaria:

import { css } from '@linaria/core';

const button = css`
  background-color: blue;
  color: white;
  padding: 10px 20px;
`;

Vanilla Extract:

import { style } from '@vanilla-extract/css';

const button = style({
  backgroundColor: 'blue',
  color: 'white',
  padding: '10px 20px'
});

Both Linaria and Vanilla Extract aim to provide zero-runtime CSS-in-JS solutions, but they differ in their approach and features. Linaria uses a more traditional CSS-like syntax with template literals, while Vanilla Extract leverages TypeScript for enhanced type safety and autocompletion.

Linaria offers better support for dynamic styles through CSS variables, making it easier to create responsive designs. However, Vanilla Extract provides more robust theming capabilities and better TypeScript integration, which can lead to improved developer experience and fewer runtime errors.

Ultimately, the choice between these two libraries depends on specific project requirements, team preferences, and the importance of TypeScript support in your development workflow.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

🧁 vanilla-extract

Zero-runtime Stylesheets-in-TypeScript.

Write your styles in TypeScript (or JavaScript) with locally scoped class names and CSS Variables, then generate static CSS files at build time.

Basically, it’s “CSS Modules-in-TypeScript” but with scoped CSS Variables + heaps more.

🔥   All styles generated at build time — just like Sass, Less, etc.

✨   Minimal abstraction over standard CSS.

🦄   Works with any front-end framework — or even without one.

🌳   Locally scoped class names — just like CSS Modules.

🚀   Locally scoped CSS Variables, @keyframes and @font-face rules.

🎨   High-level theme system with support for simultaneous themes. No globals!

🛠   Utils for generating variable-based calc expressions.

💪   Type-safe styles via CSSType.

🏃‍♂️   Optional runtime version for development and testing.

🙈   Optional API for dynamic runtime theming.


🌐 Check out the documentation site for setup guides, examples and API docs.


🖥   Try it out for yourself in CodeSandbox.


Write your styles in .css.ts files.

// styles.css.ts

import { createTheme, style } from '@vanilla-extract/css';

export const [themeClass, vars] = createTheme({
  color: {
    brand: 'blue'
  },
  font: {
    body: 'arial'
  }
});

export const exampleStyle = style({
  backgroundColor: vars.color.brand,
  fontFamily: vars.font.body,
  color: 'white',
  padding: 10
});

💡 Once you've configured your build tooling, these .css.ts files will be evaluated at build time. None of the code in these files will be included in your final bundle. Think of it as using TypeScript as your preprocessor instead of Sass, Less, etc.

Then consume them in your markup.

// app.ts

import { themeClass, exampleStyle } from './styles.css.ts';

document.write(`
  <section class="${themeClass}">
    <h1 class="${exampleStyle}">Hello world!</h1>
  </section>
`);

Want to work at a higher level while maximising style re-use? Check out 🍨 Sprinkles, our official zero-runtime atomic CSS framework, built on top of vanilla-extract.


Thanks

  • Nathan Nam Tran for creating css-in-js-loader, which served as the initial starting point for treat, the precursor to this library.
  • Stitches for getting us excited about CSS-Variables-in-JS.
  • SEEK for giving us the space to do interesting work.

License

MIT.

NPM DownloadsLast 30 Days