Build-Time CSS / Style Tag in JSX.

Write styles directly in your JSX components with zero runtime overhead. Powered by Rust for blazing-fast build times. Integrates with all popular bundlers.

Built for Modern Development

Built from the ground up with performance and developer experience in mind.

Zero-Runtime

All styles are processed at build time.

Universal Bundler Support

📦

Works with all popular bundlers. Rollup, Vite, Webpack, and Parcel.

Theming

🎨

Easily create and manage themes with design tokens.

Scoped Styles

🎯

Styles are scoped to the component, no more class name collisions.

Blazing Fast

Built with Rust for blazing-fast CSS processing, parsing, and optimization.

Preprocessor Support (Soon)

🛠️

Support for popular preprocessors like Sass and Less (coming soon).

Installation

Install the dev dependencies:

npm install @flairjs/core @flairjs/vite-plugin -D

Install the dependencies:

npm install @flairjs/client

Note: The client package will be part of your bundle only if you use the utility functions c or cn. These functions are used to forecefully include a class name when flair can't directly infer it.

Add the Vite plugin to your vite.config.ts file:

import { defineConfig } from 'vite';
import flair from '@flairjs/vite-plugin';

export default defineConfig({
  plugins: [react(), flair({
    // flair options
  })],
});

Usage

Flair gives you three ways to write CSS.

1. You can write your styles in a Style component as shown below

import { Style } from "@flairjs/client/react";
import { css } from "@flairjs/client";
  
export const App = () => {
  return (
    <>
      <h1 className="title">Hello, world!</h1>
      <Style>
        {css`
          .title {
            color: blue;
            font-size: 2rem;
          }
        `}
      </Style>
    </>
  );
};
  
The css tag is not required. Some editors / extensions might provide intellisense / syntax highlighting when using it.

2. You can write your styles by adding a flair property to your component. Its value can be a string or template literal as shown below

import { css } from "@flairjs/client";
  
export const App = () => {
  return (
    <div className="app">
      <h1 className="title">Hello, world!</h1>
    </div>
  );
};

App.flair = css`
  .app {
    padding: $space.10;
  }

  .title {
    fontSize: $fontSizes.xl;
    fontWeight: $fontWeights.bold;
  }
`;
The css tag is not required. Some editors / extensions might provide intellisense / syntax highlighting when using it.

3. You can also pass an object to the flair property as shown below

import { flair } from "@flairjs/client";
  
export const App = () => {
  return (
    <div className="app">
      <h1 className="title">Hello, world!</h1>
    </div>
  );
};

App.flair = flair({
  ".app": {
    padding: "$space.10",
  },
  ".title": {
    fontSize: "$fontSizes.xl",
    fontWeight: "$fontWeights.bold",
  },
});

Options

classNameList

Used to configure custom class names that should be picked up by Flair.
Default value is ["className", "class"].

This can be customized by passing a different array of class names. You can also use regex. Eg:

['className', 'containerClassName', new RegExp('^class[A-Z][A-Za-z0-9_]*').toString()]

include

Files to be included in flair transform

exclude

Files to be excluded in flair transform

Theming

You can create a theme system by defining a flair.theme.ts file.

Inspired from Stitches, it follows a similar pattern for the theme tokens.

import { defineConfig } from "@flairjs/client";
  
const theme = defineConfig({
  selector: ":root",
  tokens: {
    colors: {
      red: "#f00",
      blue: "#00f",
      green: {
        100: "#d4f5d4",
        200: "#aaf0aa",
        300: "#7fe67f",
      }
    },
    fontSizes: {
      sm: "14px",
      md: "16px",
    },
    fonts: {
      body: "'Martian Mono', monospace",
    },
    sizes: {},
    space: {},
    fontWeights: {},
    lineHeights: {},
    letterSpacings: {},
    radii: {},
    borders: {},
    borderWidths: {},
    shadows: {},
    zIndices: {},
    transitions: {},
  },

  breakpoints: {
    sm: "640px",
    md: "768px",
    lg: "1024px",
    xl: "1280px",
  },

  themes: {
    dark: {
      selector: ".dark",
      tokens: {
        colors: {
          bgPrimary: "#111",
        }
      }
    }
  }
});

export type Theme = typeof theme;

export default theme;

And from the CSS side, you can use the tokens like this:

flair({
  ".button": {
    backgroundColor: "$colors.green.100",
    fontSize: "$fontSizes.md",

    "@screen md": {
      fontSize: "$fontSizes.lg",
    }
  }
})

You can also bring in typescript intellisense by overriding FlairTheme in your project:

// In a .d.ts file
import { Theme } from "./flair.theme";

declare module "@flairjs/client" {
  export interface FlairTheme extends Theme {}
}