---
title: Frequently Asked Questions
description: Frequently asked questions and how to resolve common issues
---

## How does Bamboo manage style conflicts ?

When you combine shorthand and longhand properties, Bamboo will resolve the styles in a predictable way. The shorthand
property will take precedence over the longhand property.

```jsx
import { css } from '../styled-system/css'

const styles = css({
  paddingTop: '20px',
  padding: '10px',
})
```

The styles generated at build time will look like this:

```css
@layer utilities {
  .p_10px {
    padding: 10px;
  }

  .pt_20px {
    padding-top: 20px;
  }
}
```

---

## Why didn't my `className` override the component's styles?

With Vite, `cx()` resolves conflicts only when the compiler can see every Bamboo argument. An arbitrary `className` prop
remains a runtime string, so `cx(componentStyles, props.className)` is only a join and the browser picks between
same-layer declarations by stylesheet order.

The reliable fix is to stop expressing the override as an opaque class name. Accept a style object and compile
`css(base, props.css)`, where later properties win before class allocation. A declared recipe variant is another good
fit when the choices are finite.

If both arguments are analyzable at the call site, `cx(css(base), css(override))` is also composed semantically and
losing declarations are never allocated. Extraction-only CLI/PostCSS output retains the older recipe-layer override
model; Vite recipes and utilities intentionally share the global atom layer.

---

## Imported Image is not working in Vite App

This is a known limitation of Bamboo due to our static extraction approach.

> Think of it this way: there's no way for the compiler to know what the final asset URL will be since Vite controls it.

We recommend moving the imported `backgroundImage` to the `style` attribute.

```jsx
import myImageBackground from './my-image.png'

const Demo = () => {
  return (
    <p
      className={css({ bg: 'red.300', backgroundRepeat: 'repeat' })}
      style={{ backgroundImage: `url("${myImageBackground}")` }}
    >
      Hello World
    </p>
  )
}
```

---

## How to get Bamboo to work with Jest?

If you run into error messages like `SyntaxError: Unexpected token 'export'` when running Jest tests. Here's what you
can:

In your tsconfig, add

```json
{
  "compilerOptions": {
    "allowJs": true
  }
}
```

In your Jest configuration, add the `ts-jest` transformer:

```ts
export default {
  // ...
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
    '^.+\\.(ts|tsx|js|jsx)?$': 'ts-jest',
  },
}
```

In your Bamboo config, set the `outExtension` to `js`:

```ts
export default defineConfig({
  // ...
  outExtension: 'js',
})
```

---

## HMR does not work when I use `tsconfig` paths?

Bamboo tries to automatically infer and read the custom paths defined in `tsconfig.json` file. However, there might be
scenarios where the hot module replacement doesn't work.

To fix this add the `importMap` option to your `bamboo.config.js` file, setting it's value to the specified `paths` in
your `tsconfig.json` file.

```json
// tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@my-path/*": ["./styled-system/*"]
    }
  }
}
```

```js
// bamboo.config.js

module.exports = {
  importMap: '@my-path',
}
```

This will ensure that the paths are resolved correctly, and HMR works as expected.

---

## HMR not triggered

If you are having issues with HMR not being triggered after a `bamboo.config.ts` change (or one of its
[dependencies](/docs/references/config#dependencies)), you can manually specify the files that should trigger a rebuild
by adding the following to your `bamboo.config.ts`:

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

export default defineConfig({
  // ...
  dependencies: ['path/to/files/**.ts'],
})
```

---

## Why are my styles not applied?

Check that the [`@layer` rules](/docs/concepts/cascade-layers#layer-css) are set and the corresponding `.css` file is
included. [If you're not using `postcss`](/docs/installation/cli), ensure that `styled-system/styles.css` is imported
and that the `bamboo` command has been run (or is running with `--watch`).

---

## How can I debug the styles?

You can use the `bamboo debug` to debug design token extraction & css generated from files.

If the issue persists, you can try looking for it in the [issues](https://github.com/gajus/bamboocss/issues). If you
can't find it, please create a minimal reproduction and submit
[a new github issue](https://github.com/gajus/bamboocss/issues/new/choose) so we can help you.

---

## Why is my IDE not showing `styled-system` imports?

If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your
tsconfig.json file.

---

## How do I get a type with each recipe properties?

You can get a [`config recipe`](/docs/concepts/recipes#config-recipe) properties types by using `XXXVariantProps`. Let's
say you have a `config recipe` named `button`, you can import its type like this:

```ts
import { button, type ButtonVariantProps } from '../styled-system/recipes'
```

---

You can get an [`inline recipe`](/docs/concepts/recipes#inline-recipe-or-cva) properties types by using
`RecipeVariantProps`. Let's say you have an `inline recipe` named `button`, you can get its type like this:

```ts
import { cva, type RecipeVariantProps } from '../styled-system/css'

export type ButtonVariantProps = RecipeVariantProps<typeof buttonStyle>
```

---

## How do I split recipe props from the rest?

You can split recipe props by using `xxx.splitVariantProps`. Let's say you have a `recipe` named `button`, you can split
its props like this:

```tsx Button.tsx {8}
import { css, cx } from '../styled-system/css'
import { ButtonVariantProps, button } from '../styled-system/recipes'

interface ButtonProps extends ButtonVariantProps {
  children: React.ReactNode
}

export function Button(props: ButtonProps) {
  const { children, ...rest } = props
  const [buttonProps, cssProps] = button.splitVariantProps(rest)
  return <button className={cx(button(buttonProps), css(cssProps))}>{children}</button>
}
```

The same `xxx.splitVariantProps` method is available for both `config recipes` and `inline recipes`.

---

## How do I reference a token value or css var?

You can reference a token value or it's associated css variable using the
[`token` function](/docs/theming/usage#vanilla-js). This function allows you to access and use the values stored in your
theme tokens at runtime.

```tsx
import { token } from '../styled-system/tokens'

function App() {
  return (
    <div
      style={{
        background: token('colors.blue.200'),
      }}
    />
  )
}
```

---

## Should I commit the styled-system folder?

Just like the `node_modules` folder, you most likely don't want to commit the `styled-system` folder. It contains code
that is auto-generated and can be re-generated at any time.

---

## How is Bamboo CSS different from Panda CSS?

Bamboo CSS is a fork of Panda CSS v1. `css`, `cva`, `sva`, `cx`, the pattern functions, recipes, tokens, conditions and
the config shape all carry over, so [migrating](/docs/migration/panda) is largely a rename — but not entirely. Three
things differ: the API is smaller, a few things behave differently, and the output is leaner.

Every number below was measured against this repository's own sandboxes and fixtures. Your project will differ – the
output-size wins in particular scale with the size of your design system rather than the size of your app.

### A smaller API

Bamboo deliberately has one way to write a style, rather than several.

- **There is no JSX factory.** `styled.div`, `styled('button', recipe)`, `createStyleContext` and `splitCssProps` have
  no equivalent, and `styled-system/jsx` is not generated at all. Style props become a `css()` call, and a recipe
  component becomes an ordinary component that calls the recipe. `jsxFramework`, `jsxFactory` and `jsxStyleProps` are
  gone from the config with them.
- **There are no JSX pattern components.** `<Stack>`, `<Box>` and the rest are not generated. The pattern _functions_
  are what those components wrapped — see [patterns](/docs/concepts/patterns) for the set that survives.
- **There is no template literal syntax.** ``css`color: red` `` is not supported; write the object form.

The result is that a class name in Bamboo always comes from a function call you can see, which is what makes the
[build-time compiler](/docs/guides/source-transformation) able to resolve the complete style graph.

### Different behaviour

These compile unchanged and do something else, so they are worth checking on migration.

- **`cx` composes what the compiler can see.** Fully analyzable Bamboo arguments are merged as StyleSets before atom
  allocation. With an arbitrary external class, `cx` remains a tiny string joiner and makes no semantic conflict
  guarantee. See [`cx` joins external classes](/docs/migration/panda#cx-joins-in-both-tools).
- **Vite compiles recipes to shared atoms.** An inline or config recipe selection resolves into the same declaration
  pool as `css()`. Recipe identity does not enter class identity, and analyzable `cx()` composition is resolved before
  classes are allocated. See
  [Vite compiles recipes to shared atoms](/docs/migration/panda#vite-compiles-recipes-to-shared-atoms).
- **Slot recipes return compiled slot atoms.** Static selections become literal slot objects; finite runtime axes become
  reduced lookups of complete slot objects. No named slot selector or `@scope` is emitted by Vite.
- **Compound variants are resolved into complete leaves.** They add no selector or runtime matcher; each selected leaf
  already contains the precedence-correct declarations.

### Less CSS

- [`prune.tokens`](/docs/references/config#prune) drops token CSS variables nothing can reach. The token layer declares
  every token in your theme while an app uses a fraction of them, so this is usually the largest single saving. On the
  example apps here it is worth 36% to 78% of `styles.css` – the `next-js-app` sandbox goes from 18,032 to 3,959 bytes,
  4,828 to 1,525 gzipped.
- [`prune.keyframes`](/docs/references/config#prune) does the same for `@keyframes` rules a preset declares and your app
  never animates.

Both are on by default; set either to `false` to opt out.

- [`preflight.prune`](/docs/references/config#preflightprune) drops the parts of the reset that style elements your
  source never renders. The reset is a fixed size, so it dominates a small stylesheet – a third of one sandbox's CSS
  here and four fifths of another's. Worth a further 13% to 38%, and unlike most CSS size work it holds up under
  compression, because it emits less rather than spelling the same thing differently.

This one is off by default and cannot be made safe by default: it has a textual scan of your own source and nothing
else, so an element rendered by a dependency, by `dangerouslySetInnerHTML`, or by markdown is invisible to it.

### Less JavaScript

- The generated output now declares `sideEffects`, so a bundler can tree-shake the barrels. Previously
  `import { box } from 'styled-system/patterns'` retained every pattern module.
- There is no JSX factory to import at all, so `styled-system/jsx` — previously the largest generated barrel — is not
  generated.

### Compiled zero-runtime styling

[`@bamboocss/vite`](/docs/guides/source-transformation) compiles style calls to globally shared declaration atoms in
development and production:

```tsx
// you write
export const title = css({ fontSize: 'lg', fontWeight: 'bold' })

// the bundle gets
export const title = 'fs_lg fw_bold'
```

A style that varies is expressed as a finite recipe axis. The build resolves compound variants and precedence for every
reachable state and emits a reduced decision table:

```tsx
const title = cva({
  base: { fontSize: 'lg' },
  variants: { weight: { bold: { fontWeight: 'bold' }, normal: { fontWeight: 'normal' } } },
})

title({ weight })
```

Recipe identity is discarded after selection, so the same declaration in this recipe, another recipe, or `css()` uses
one atom. Recipe declarations are erased from JavaScript and the named recipe CSS layer is not emitted. Open runtime
style values are compiler errors; there is no option that restores a runtime styling fallback.

---

## How does Bamboo work?

When running `pnpm bamboo`, here's what's happening under the hood:

- **Load Bamboo context**:
  - Find and evaluate app config, merge result with presets.
  - Create bamboo context: prepare code generator from config, parse user's file as AST.
- **Generating artifacts**:
  - Write lightweight JS runtime and types to output directory
- **Extracting used styles in app code**:
  - Run parser on each user's file: identify and extract styles, compute CSS, write to styles.css.

---

## I'm seeing a "Could not resolve xxx" error with esbuild/tsdown. What should I do?

In such a case, check the [`outExtension`](/docs/references/config#outextension) in your `bamboo.config` and set it to
"js". This will ensure your modules are resolved correctly.

---

## Why is my preset overriding the base one, even after adding it to the array?

You might have forgotten to include the `extend` keyword in your config. Without `extend`, your preset will completely
replace the base one, instead of merging with it.

---

## Why is my base condition not working in this example?

```ts
css({ color: { _base: 'red.600', _dark: 'white' } })
```

You used `_base` instead of `base`, there is no underscore `_`.

---

## What's the difference between using `defineConfig()` vs `definePreset()`

`defineConfig` is intended to be used in your app config, and will show you all the config keys that are available.
`definePreset` will only show you the config keys that will be merged into an app's config, the rest will be ignored.

---

## How can I completely override the default tokens?.

If you want to **completely override all** of the default presets theme tokens, you can omit the `extends` keyword from
your `theme` config object.

If you want to **keep some of the defaults**, you can install the `@bamboocss/preset-bamboo` package, import it, then
specifically pick what you need in there (or use the JS spread operator `...` and override the other keys).

---

## How do I make a design system / component library with Bamboo?

There is a detailed guide on how to do this [here](/docs/guides/component-library).

---

## Can I use dynamic styles with Bamboo?

Yes, when the set of styles is finite. Declare runtime choices as recipe variants; Bamboo compiles the possible states
to a reduced decision table. Open values such as `css({ color: userValue })` are rejected because they have no finite
build-known CSS rule set. See [Source compilation](/docs/guides/source-transformation#what-compiles).

---

## Can Bamboo resolve styles at build time instead of at runtime?

Yes. `@bamboocss/vite` compiles style calls to shared declaration atoms in development and production:

```tsx
export const title = css({ fontSize: 'lg' })
export const title = 'fs_lg'
```

It covers `css()`, patterns, recipes, finite runtime recipe axes, tokens, static `viewTransition()` bags, and analyzable
`cx()`. Open runtime style values fail compilation instead of retaining the style engine. See
[Source compilation](/docs/guides/source-transformation).

---

## Should I use atomic or config recipes ?

Under the Vite compiler both resolve to the same globally shared declaration atoms. The difference is where the recipe
is declared and whether Bamboo can build a finite runtime decision table:

- A **config recipe** is declared in `theme.recipes` under a key and can be shared through presets.
- An **inline recipe** (`cva`) is colocated with the component.

Both support finite runtime axes under Vite. The choice is preset sharing versus colocation. See
[Should I use an inline or config recipe?](/docs/concepts/recipes#should-i-use-an-inline-or-config-recipe) for the full
comparison table — kept there rather than duplicated here, since a copy of it in this page went stale once already.

---

## Why does the bamboo codegen command fail ?

If you run into any error related to "Transforming const to the configured target environment ("es5") is not supported
yet", update your tsconfig to use es6 or higher:

```json filename="tsconfig.json"
{
  "compilerOptions": {
    "target": "es6"
  }
}
```

---

## How can I generate all possible CSS variants at build time?

While it's possible to generate all variants, even unused ones, by using
[`config.staticCss`](https://bamboocss.com/docs/guides/dynamic-styling#using-static-css), it's generally **not
recommended** to use it for more than a few values. However, keep in mind this approach compromises one of Bamboo's
strengths: lean, usage-based CSS generation.

---

## Can I use one-off media query and other at rules?

Yes, you can! You can apply one-off media queries and other at rules (such as `@container`, `@supports`) in your CSS as
shown below:

```javascript
css({
  containerType: 'size',
  '@media (min-width: 10px)': {
    fontSize: 'xl',
    color: 'blue.300',
  },
  '@container (min-width: 10px)': {
    fontSize: '2xl',
    color: 'green.300',
  },
  '@supports (display: flex)': {
    fontSize: '3xl',
    color: 'red.300',
  },
})
```

---

## How can I prevent other libraries from overriding my styles?

You can use
[Layer Imports](<https://developer.mozilla.org/en-US/docs/Web/CSS/@import#layer-name:~:text=%40import%20url%20layer(layer%2Dname)%3B>)
to prevent other libraries from overriding your styles.

First of all you cast the css from the other library(s) to a css layer:

```css
@import url('bootstrap.css') layer(bootstrap);

@import url('ionic.css') layer(ionic);
```

Then update the default layer list to deprioritize the styles from the other library(s):

```css
@layer bootstrap, reset, base, tokens, recipes, utilities;

@layer ionic, reset, base, tokens, recipes, utilities;
```
