StyleX

repository·main·Indexed 27 days ago

https://github.com/facebook/stylex

A JavaScript library for defining styles for optimized user interfaces, providing a type-safe and performant CSS-in-JS system. It includes @stylexjs/atoms for atomic styles, @stylexjs/babel-plugin for transformation and CSS extraction, @stylexjs/cli for pre-compilation, @stylexjs/eslint-plugin for style validation and linting, and a Chrome DevTools extension for debugging.

Tokens
67.3K
Snippets
225
Records
347
Agent score
94%

What's inside StyleX

  1. Overview of StyleX

    main

    StyleX is an expressive, deterministic, and scalable styling system designed for large-scale applications. It combines the developer experience of CSS-in-JS with the performance of static CSS by using compile-time tooling (primarily a Babel plugin) to transform styles into optimized, atomic CSS class names.

    Key features include:

    • Atomic CSS: Automatically transforms styles into atomic class names, minimizing CSS bundle size.
    • Predictable Specificity: Manages CSS specificity automatically to ensure that the last style applied always wins, preventing specificity conflicts.
    • Type-Safety: Fully compatible with TypeScript and Flow, allowing for fine-grained control over style properties and values.
    • Composition: Supports merging styles across file and component boundaries.
    • Zero Runtime (Static): If a component defines and uses styles within the same file statically, the runtime cost is zero.
    • Colocation: Encourages authoring styles in the same file as the component for better maintainability.
  2. Overview of style-value-parser

    main
    The style-value-parser is an experimental CSS value parser designed specifically for StyleX. It is built on top of @csstools/css-tokenizer and serves as a high-performance, customizable replacement for postcss-value-parser. It is intended to enable stricter parsing and better control over style property values within the StyleX ecosystem.
  3. Core Components of the StyleX Toolchain

    main

    StyleX operates through a collection of integrated tools:

    • Babel Plugin: The core engine that finds, extracts, and converts styles into atomic class names at compile time.
    • Runtime Library: A small, highly optimized library used for merging class names dynamically when using powerful patterns like style composition.
    • ESLint Plugin: Provides linting support for StyleX usage.
    • Integrations: A collection of plugins for bundlers (e.g., Rollup, Vite, Rspack) and frameworks.
  4. Configure StyleX with RedwoodSDK and Vite

    main

    To use StyleX with RedwoodSDK's Vite-based toolchain, use @stylexjs/unplugin in your vite.config.mts. The configuration should use devMode: 'css-only' to expose the /virtual:stylex.css endpoint (since Redwood manages HTML injection) and devPersistToDisk: true to share collected rules across multiple Vite environments (worker and client).

    Required stylex.vite options:

    • devMode: 'css-only'
    • devPersistToDisk: true
    • dev: true
    • runtimeInjection: false
    import { defineConfig } from 'vite';
    import { redwood } from 'rwsdk/vite';
    import { cloudflare } from '@cloudflare/vite-plugin';
    import stylex from '@stylexjs/unplugin';
    
    export default defineConfig({
      plugins: [
        cloudflare({ viteEnvironment: { name: 'worker' } }),
        redwood(),
        stylex.vite({
          devMode: 'css-only',
          devPersistToDisk: true,
          dev: true,
          runtimeInjection: false,
        }),
      ],
    });
  5. Enable Hot Reloading and CSS Injection in React Router (RSC)

    main

    To enable hot reloading during development and proper CSS linking in production, use a helper component like DevStyleXInject. This component imports the virtual:stylex:runtime during development and renders a <link> tag for the virtual CSS file. In production, it renders a <link> tag pointing to your production CSS href.

    Render <DevStyleXInject /> inside the <head> of your HTML shell component.

    // src/DevStyleXInject.tsx
    'use client';
    import { useEffect } from 'react';
    
    function DevStyleXInjectImpl() {
      useEffect(() => {
        if (import.meta.env.DEV) {
          import('virtual:stylex:runtime');
        }
      }, []);
      return <link rel="stylesheet" href="/virtual:stylex.css" />;
    }
    
    export function DevStyleXInject({ cssHref }: { cssHref: string }) {
      return import.meta.env.DEV ? (
        <DevStyleXInjectImpl />
      ) : (
        cssHref && <link rel="stylesheet" href={cssHref} />
      );
    }
  6. Configure StyleX with Webpack

    main

    Use stylex.webpack() in your Webpack plugins. Ensure you are using a CSS extraction plugin (like MiniCssExtractPlugin) so StyleX has a CSS asset to append to.

    // webpack.config.js
    const stylex = require('@stylexjs/unplugin').default;
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
    module.exports = {
      module: {
        rules: [
          // your JS/TS loader here
          { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] },
        ],
      },
      plugins: [stylex.webpack({ useCSSLayers: true }), new MiniCssExtractPlugin()],
    };
  7. Configure PostCSS for StyleX in Next.js

    main

    Create a postcss.config.js file. This configuration should import your babel.config.js to ensure consistency between the Babel and PostCSS plugins. Use the include option with glob patterns to specify which source files contain StyleX styles. Setting useCSSLayers: true is recommended.

    const babelConfig = require('./babel.config');
    
    module.exports = {
      plugins: {
        '@stylexjs/postcss-plugin': {
          include: [
            // when using a src folder:
            'src/**/*.{js,jsx,ts,tsx}',
            // app router:
            'app/**/*.{js,jsx,ts,tsx}',
            // pages router:
            'pages/**/*.{js,jsx,ts,tsx}',
            // other top-level folders:
            'components/**/*.{js,jsx,ts,tsx}',
          ],
          babelConfig: {
            babelrc: false,
            parserOpts: { plugins: ['typescript', 'jsx'] },
            plugins: babelConfig.plugins,
          },
          useCSSLayers: true,
        },
        autoprefixer: {},
      },
    };
  8. Use the StyleX CLI to pre-transform files

    main

    The StyleX CLI is used to pre-transform a directory of files to compile away StyleX and generate a static CSS file. This should run before your main build pipeline.

    Requirement: Your bundler must be able to handle CSS imports, because the CLI inserts an import for the generated CSS file into every transformed file.

    To run the compiler, use the stylex command with the --config flag pointing to your configuration file. Use the --watch flag for incremental rebuilds.

    {
      "scripts": {
        "build": "stylex --config .stylex.json5",
        "watch": "stylex --config .stylex.json5 --watch"
      }
    }