---
title: Migrating from Stitches
description: Migrate your project from Stitches to Bamboo.
---

This guide helps you migrate from Stitches to Bamboo and understand the design differences between the libraries.

> **Disclaimer:** This isn't about comparing which one is best. Bamboo and Stitches are two different CSS-in-JS
> solutions with design decisions.

Here are some similarities between the two libraries.

- Bamboo uses the object literal syntax to define styles. It also supports the shorthand syntax for the `margin` and
  `padding` properties.
- Bamboo supports the `variants`, `defaultVariants` and `compoundVariants` APIs.
- Bamboo supports design tokens and themes.
- Bamboo supports all the variants of nested selectors (attribute, class, pseudo, descendant, child, sibling selectors
  and more). It also requires the use of the `&` to chain selectors.

Below are some of the differences between the two libraries.

## css function

In Stitches, the `css` function is used to author both regular style objects and variant style objects.

```tsx
import { css } from '@stitches/react'

// definition
const styles = css({
  border: 'solid 1px red',
  backgroundColor: 'transparent',

  variants: {
    variant: {
      // ...
    }
  }
})

// usage
<button className={styles({ variant: 'primary' })} />
```

In Bamboo, the `css` function is only used to author atomic styles, and the `cva` function to create variant style
objects.

**The css function**

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

// definition
const styles = css({
  border: 'solid 1px red',
  backgroundColor: 'transparent'
})

// usage
<button className={styles} />
```

**The cva function**

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

// definition
const styles = cva({
  base: {
    border: 'solid 1px red',
    backgroundColor: 'transparent'
  },
  variants: {
    variant: {
      // ...
    }
  }
})

// usage
<button className={styles({ variant: 'primary' })} />
```

## styled function

In Stitches, the `styled` function creates components bound to both regular and variant style objects, and generates a
unique className for each variant.

```tsx
import { styled } from '@stitches/react'

const Button = styled('button', {
  // base styles
  backgroundColor: 'gainsboro',
  borderRadius: '9999px',

  variants: {
    // variant styles
  },
})
// => <button class="c-coNKBW c-coNKBW-dnSdJM-variant-primary">Button</button>
```

Bamboo has no `styled` factory. Base styles go under the `base` key of a recipe. With Vite, inline and configured
recipes compile into the same globally shared atom pool; the choice is about organization and generated API, not CSS
identity.

- **Colocated** with the component, using the `cva` function. Static selections compile directly; finite runtime axes
  compile to reduced decision tables containing only complete reachable style sets.

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

const button = cva({
  className: 'button',
  base: {
    backgroundColor: 'gainsboro',
    borderRadius: '9999px',
  },
})
// => <button class="button">Button</button>
```

`className` is optional extraction metadata. It does not enter Vite's declaration identity or the names of the atoms it
emits.

- **In the config**, by defining the recipe in `bamboo.config.ts`. It uses the same Vite lowering as an inline recipe,
  while codegen exposes a named import and its variant types.

```ts
import { defineConfig, defineRecipe } from '@bamboocss/dev'

const buttonStyle = defineRecipe({
  className: 'button',
  base: {
    backgroundColor: 'gainsboro',
    borderRadius: '9999px',
  },
  variants: {
    // variant styles
  },
})

export default defineConfig({
  theme: {
    extend: {
      recipes: {
        buttonStyle,
      },
    },
  },
})
```

> You might need to run `bamboo codegen --clean` to generate the recipe functions.

```tsx
import { buttonStyle } from '../styled-system/recipes'
;<button className={buttonStyle({ variant: 'primary' })}>Button</button>

// => <button className="button button--variant_primary">Button</button>
```

## Responsive Styles

In Stitches, you configure breakpoints in the `media` key of the `createStitches` method, and use it via the
`@<breakpoint>` syntax.

```ts
import { createStitches } from '@stitches/react'

// configure
const { styled, css } = createStitches({
  media: {
    bp1: '(min-width: 640px)',
    bp2: '(min-width: 768px)',
  },
})

// usage
const styles = css({
  backgroundColor: 'gainsboro',
  '@bp1': {
    backgroundColor: 'tomato',
  },
})
```

In Bamboo, you configure breakpoints in the `theme.breakpoints` key of the `bamboo.config` function

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

export default defineConfig({
  theme: {
    extend: {
      breakpoints: {
        bp1: '640px',
        bp2: '768px',
      },
    },
  },
})

// usage
import { css } from '../styled-system/css'

const styles = css({
  bg: 'gainsboro',
  bp1: { bg: 'tomato' },
  // or
  margin: { base: '10px', bp1: '20px' },
})
```

In Stitches, you use the `@initial` keyword to target the base styles.

In Bamboo, you use the `base` key to target the base styles.

## Tokens and Theme

### Tokens

In Stitches, tokens are defined in the `theme` key of the `createStitches` method.

```ts
import { createStitches } from '@stitches/react'

const { styled, css } = createStitches({
  theme: {
    colors: {
      gray100: 'hsl(206,22%,99%)',
      gray200: 'hsl(206,12%,97%)',
    },
  },
  space: {},
  fonts: {},
})

// usage
const styles = css({
  backgroundColor: '$gray100',
})
```

In Bamboo, tokens are defined in the `theme` key of the `bamboo.config` function.

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

export default defineConfig({
  theme: {
    tokens: {
      colors: {
        gray100: { value: 'hsl(206,22%,99%)' },
        gray200: { value: 'hsl(206,12%,97%)' },
      },
      spacing: {},
      fonts: {},
    },
    semanticTokens: {
      // ...
    },
  },
})

// usage
import { css } from '../styled-system/css'

const styles = css({
  backgroundColor: 'gray100',
})
```

Notice that in Bamboo, you don't need to use the `$` prefix to access the tokens. If you want to keep it across the
board, format the token names in a hook rather than renaming every token:

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

export default defineConfig({
  // ...
  plugins: [
    {
      name: 'stitches-token-names',
      hooks: {
        'tokens:created': ({ configure }) => {
          configure({
            formatTokenName: (path) => '$' + path.join('-'),
          })
        },
      },
    },
  ],
})
```

### Themes

In Stitches, the `createTheme` function is used to define dark theme values.

```tsx
import { createStitches } from '@stitches/react'

const { createTheme } = createStitches({})

// create theme
const darkTheme = createTheme({
  colors: {
    gray100: 'hsl(206,8%,12%)',
    gray200: 'hsl(206,7%,14%)'
  }
})

// apply theme
<div className={darkTheme}>
  <div>Content nested in dark theme.</div>
</div>
```

In Bamboo, themes are designed as semantic tokens. You can define the semantic tokens in the `semanticTokens` key of the
`bamboo.config` function.

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

export default defineConfig({
  theme: {
    semanticTokens: {
      colors: {
        gray100: {
          value: { base: 'hsl(206,22%,99%)', _dark: 'hsl(206,8%,12%)' },
        },
        gray200: {
          value: { base: 'hsl(206,12%,97%)', _dark: 'hsl(206,7%,14%)' },
        },
      },
    },
  },
})
```

### Token Aliases

In Stitches, you can create locally scoped tokens using the `$$` prefix

```ts
import { styled } from '@stitches/react'

const Button = styled('button', {
  $$shadowColor: '$colors$pink500',
  boxShadow: '0 0 0 15px $$shadowColor',
})
```

In Bamboo, there's no special syntax, you need to use the css variable syntax. CSS variables are able to query the theme
tokens directly using dot notation

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

const button = css({
  '--shadowColor': 'colors.pink500',
  boxShadow: '0 0 0 15px var(--shadowColor)',
})
```

## Animations

In Stitches, you can define keyframes using the `keyframes` method.

```ts
import { keyframes, styled } from '@stitches/react'

const scaleUp = keyframes({
  '0%': { transform: 'scale(1)' },
  '100%': { transform: 'scale(1.5)' },
})

// usage
const Button = styled('button', {
  '&:hover': {
    animation: `${scaleUp} 200ms`,
  },
})
```

In Bamboo, you define keyframes in the `theme.keyframes` key of the `bamboo.config` function.

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

export default defineConfig({
  theme: {
    extend: {
      keyframes: {
        scaleUp: {
          '0%': { transform: 'scale(1)' },
          '100%': { transform: 'scale(1.5)' },
        },
      },
    },
  },
})

// usage
import { css } from '../styled-system/css'

const style = css({
  '&:hover': {
    animation: 'scaleUp 200ms',
  },
})
```

## Utils

In Stitches, you can define utilities by using the `utils` key in the `createStitches` method.

```ts
import { createStitches, type PropertyValue } from '@stitches/react'

const { styled, css } = createStitches({
  utils: {
    linearGradient: (value: PropertyValue<'backgroundImage'>) => ({
      backgroundImage: `linear-gradient(${value})`,
    }),
  },
})
```

In Bamboo, you get a lot of built-in utilities (like mx, marginX, my, py, etc.) that you can use out of the box. You can
also create custom utilites using the `utilities` key in the `bamboo.config` function.

The utilities API allows you define the connected token scale, generated className, and transform function.

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

export default defineConfig({
  utilities: {
    extend: {
      linearGradient: {
        // (optional): the css property this maps to (to inherit the types from)
        property: 'backgroundImage',
        // (optional): the className to generate
        className: 'bg_gradient',
        // (optional): the shorthand name to use in the css
        shorthand: 'gradient',
        // (required): maps the value to the raw css object
        transform: (value) => ({
          backgroundImage: `linear-gradient(${value})`,
        }),
      },
    },
  },
})
```

> Running `bamboo codegen` will update the typings for the utilities, allowing for a type-safe developer experience.

Then you can use the utility in your styles.

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

const buttonClass = css({
  linearGradient: '19deg, #21D4FD 0%, #B721FF 100%',
})
```

## Global Styles

In Stitches, you define the global styles using the `global.css` function, and then call it in your app.

```tsx
import { globalCss } from '@stitches/react'

const globalStyles = globalCss({
  '*': { margin: 0, padding: 0 },
})

// then in your app
globalStyles()
```

In Bamboo, you define the global styles in the `bamboo.config.ts` under `global.css`, using the `defineGlobalStyles`
helper.

> The styles are injected automatically under the `base` cascade layer via PostCSS

```ts {3-5}
import { defineConfig, defineGlobalStyles } from '@bamboocss/dev'

const globalCss = defineGlobalStyles({
  '*': { margin: 0, padding: 0 },
})

export default defineConfig({
  // ...
  global: { css: globalCss },
})
```

## Targeting Components

In Stitches, you can directly target React or styled components via the `toString()` method.

```tsx
import { css } from '@stitches/react'

const Icon = () => (
  <svg className="right-arrow" ... />
);

// add a `toString` method
Icon.toString = () => '.right-arrow';

const buttonClass = css({
  [`& ${Icon}`]: {
    marginLeft: '5px'
  }
})
```

In Bamboo, you need to use the native selector directly. This is largely due to the static nature of Bamboo

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

const Icon = () => (
  <svg className="right-arrow" ... />
);


const buttonClass = css({
  "& .right-arrow": {
    marginLeft: '5px'
  }
})
```

## Server Side Rendering

Stitches needs per-framework SSR wiring — `getCssText()` from `createStitches`, and its output placed into the document
head by hand.

Bamboo needs none of it. Styles are extracted and emitted at build time by PostCSS, so there is nothing to collect at
request time.

## Conclusion

Before choosing your preferred CSS-in-JS library, be sure to consider your engineering and design goals. Both Stitches
and Bamboo are capable of achieving many of the same styling goals, but they have different approaches.
