---
title: Static CSS Generator
description: Bamboo can be used to generate a static set of utility classes for your project.
---

Bamboo can be used to generate a static set of utility classes for your project.

This is useful if you want to use Bamboo in an HTML project or you want absolute zero runtime.

## Usage

To generate a static set of CSS classes, add them to your `bamboo.config.js` file:

```js
export default {
  staticCss: {
    // the css properties you want to generate
    css: [],
    // the recipes you want to generate
    recipes: {},
    // the patterns you want to generate
    patterns: {},
    // the theme variants you want to generate
    themes: [],
  },
}
```

The `staticCss` property supports four properties:

- `css` - an array of CSS rules you want to generate, each with their `conditions`
- `recipes` - the component recipes you want to generate, or `'*'` for every recipe and every variant
- `patterns` - the patterns you want to generate, keyed by pattern name
- `themes` - the [theme variants](/docs/guides/multiple-themes#pregenerating-themes) to include in the CSS output

## Generating CSS Properties

The `css` property is an array of CSS properties you want to generate with their `conditions`.

You can specify the following options:

- `properties`: an object mapping each CSS property to the array of values to generate for it. `'*'` stands for every
  value the tokens define; any other entry is generated as written.
- `conditions`: the CSS conditions or selectors you want to generate in addition to the default values. Values can be
  `light, dark`, etc.
- `responsive`: whether or not to generate responsive classes

```js
export default {
  staticCss: {
    css: [
      {
        properties: {
          margin: ['*'],
          padding: ['*', '50px', '80px'],
        },
        responsive: true,
      },
      {
        properties: {
          color: ['*'],
          backgroundColor: ['green.200', 'red.400'],
        },
        conditions: ['light', 'dark'],
      },
    ],
  },
}
```

## Generating Recipes

The `recipes` property is an object of component recipes you want to generate with their `conditions`.

```js
export default {
  staticCss: {
    recipes: {
      button: [
        {
          size: ['sm', 'md'],
          responsive: true,
        },
        { variant: ['*'] },
      ],
      // shorthand for all variants
      tooltip: ['*'],
    },
  },
}
```

You can also directly specify a recipe's `staticCss` rules from inside a recipe config, e.g.:

```js
import { defineRecipe } from '@bamboocss/dev'

const card = defineRecipe({
  className: 'card',
  base: { color: 'white' },
  variants: {
    size: {
      small: { fontSize: '14px' },
      large: { fontSize: '18px' },
    },
  },
  staticCss: [{ size: ['*'] }],
})
```

would be the equivalent of defining it inside the main config:

```js
import { defineConfig } from '@bamboocss/dev'

export default defineConfig({
  // ...
  staticCss: {
    recipes: {
      card: [{ size: ['*'] }],
    },
  },
})
```

Or you could even generate the CSS for every config `recipe` / `slotRecipes` (and each of their variants):

```tsx filename="bamboo.config.ts"
import { defineConfig } from '@bamboocss/dev'

export default defineConfig({
  // ...
  staticCss: {
    recipes: '*',
  },
})
```

This is mostly useful for testing purposes with [`Storybook`](/docs/installation/storybook).

## Generating Patterns

The `patterns` property is an object of patterns, each taking the same rules as `css`. The properties are the pattern's
own props rather than CSS properties, and `'*'` covers every prop the pattern declares.

```js
export default {
  staticCss: {
    patterns: {
      flex: [{ properties: { gap: ['*'], align: ['center'] } }],
      // shorthand for every prop of the pattern
      center: ['*'],
    },
  },
}
```

## Generating Themes

`themes` lists the [theme variants](/docs/guides/multiple-themes#pregenerating-themes) to emit. No theme variant reaches
the CSS output unless it is named here.

```js
export default {
  staticCss: {
    themes: ['primary', 'secondary'],
  },
}
```

## Performance Considerations

Pre-generating large numbers of styles costs build time and CSS size. Only generate the styles you actually need.

### Best Practices

**❌ Avoid: Generating every possible combination**

```js
export default {
  staticCss: {
    css: [
      {
        conditions: ['hover', 'focus', 'active', 'disabled'],
        properties: {
          // This expands to ALL tokens - very expensive!
          color: ['*'],
          backgroundColor: ['*'],
          borderColor: ['*'],
          width: ['*'],
          height: ['*'],
          // ... 20+ more properties with wildcards
        },
      },
    ],
  },
}
```

**✅ Better: Only generate what you need**

```js
export default {
  staticCss: {
    css: [
      {
        conditions: ['_hover', '_focus'],
        properties: {
          // Only the colors you actually use
          color: ['red.500', 'blue.500', 'gray.600'],
          backgroundColor: ['white', 'gray.50', 'blue.50'],
          borderColor: ['gray.200', 'blue.500'],
        },
      },
    ],
  },
}
```

### When to Use Wildcards

Wildcards (`['*']`) are appropriate when:

- **Small token sets**: Properties with < 20 values (e.g., `fontWeight: ['*']`)
- **Critical utilities**: Styles you genuinely need in all variants
- **Testing scenarios**: Storybook or visual regression testing

### Use Responsive Selectively

The `responsive` property multiplies the number of generated classes by your breakpoints. Only enable it for properties
that genuinely need responsive behavior.

Properties that commonly need `responsive: true`:

- Layout: `display`, `flexDirection`, `gridTemplateColumns`
- Sizing: `width`, `height`, `maxWidth`
- Spacing: `padding`, `margin`, `gap`
- Positioning: `position`, `top`, `left`

Properties that rarely need `responsive: true`:

- Colors: `color`, `backgroundColor`, `borderColor`
- Typography: `fontWeight`, `textDecoration`, `fontFamily`
- Effects: `boxShadow`, `opacity`, `cursor`

## Removing unused CSS

Reach for [`prune`](/docs/references/config#prune) first — it drops token declarations, `@property` registrations and
keyframes the finished stylesheet cannot reach, and [`preflight.prune`](/docs/references/config#preflightprune) drops
the parts of the reset that style elements you never render. These read the build's own output rather than guessing from
your markup, so they are safe in ways a selector scan is not.

Note that `staticCss` works against them: every rule it emits is a rule the pruning has to keep, along with whatever it
references. If you added a `staticCss` entry to stop a token category being pruned, use
[`prune.keepTokens`](/docs/references/config#prunekeeptokens) instead — it keeps the declarations without emitting a
rule per value to hold them up.

For an even smaller css output size, you can utilize [PurgeCSS](https://purgecss.com/) to treeshake and remove unused
CSS. This tool will analyze your template and match selectors against your CSS.
