Why Bamboo
From the endless list of CSS-in-JS libraries, why should you choose Bamboo?
Styles that resolve before they ship
Bamboo is a build-time CSS-in-JS engine. You write style objects; the Vite compiler resolves them into globally shared
atoms and replaces every style-producing call with a literal or finite lookup. Open runtime styling is rejected. Nothing
generates styles in the browser or injects them into the <head>.
Three things follow from that, and they are what Bamboo is for.
The call disappears
Every class name comes from a function call the compiler can see. There is no JSX factory, no template literal syntax and no style props, so the compiler can remove the call entirely:
// you write
export const title = css({ fontSize: 'lg', fontWeight: 'bold' })
// the bundle gets
export const title = 'fs_lg fw_bold'
A style that varies uses a declared, finite recipe axis. Bamboo precompiles every reachable StyleSet and leaves only a
small decision table behind. An open value such as css({ color: tone }) is rejected because no finite stylesheet can
back every value it might produce.
The payoff is larger than the CPU saved per call. Recipe configs and the style engine disappear from the production
graph, while identical declarations from every recipe and css() call share one atom and one CSS rule.
A green build means a complete stylesheet
Static extraction's characteristic failure is silence. A file the parser threw on, a call to a pattern a preset dropped,
a background: 'accent.default' naming a token that does not exist — each contributes no rule, and nothing downstream
objects, because a stylesheet missing rules is still a valid stylesheet. The class the component asks for simply has
nothing behind it, and it surfaces much later as "this colour never applied", a long way from the edit that caused it.
Bamboo treats that as a build failure rather than a fact of life:
ERR_BAMBOO_DEAD_IMPORT: 12 call(s) name a binding that does not exist:
`stack` is not a pattern — `../styled-system/patterns` does not export it.
12 file(s): src/modal.tsx, src/drawer.tsx, src/sheet.tsx, … and 9 more
Build diagnostics lists what is checked, what each check costs, and which of them you can grade.
You ship what you use
The token layer declares every token in your theme while an app uses a fraction of them, so
pruning what nothing can reach is usually the largest single saving in render-blocking
CSS — 36% to 78% of styles.css on the example apps in this repository. The same applies to @keyframes a preset
declares and your app never animates, and to the parts of the reset that style elements your source never renders.
Built at scale
Bamboo is the styling engine behind Contra (opens in a new tab), whose UI has more than 20,000 css() call sites. At
that scale everything a styling library spends per call site – bytes emitted, work at runtime, time in the build – is
multiplied by five figures, so optimizations too small to notice elsewhere are plainly measurable. Bamboo exists to
chase them further than a general-purpose library reasonably would.
It began as a fork of Panda CSS (opens in a new tab) and keeps its authoring primitives: css, cva, sva, cx,
patterns and recipes. The API is smaller and several behaviours differ — analyzable cx calls compose StyleSets,
recipes share global atoms, and slot selections compile directly to per-slot atom strings — so if you are coming from
Panda, read what changed before you
migrate.
When to use Bamboo?
Bamboo suits an app whose stylesheet is starting to track the size of its design system rather than the size of its own UI, and a team that would rather have an extraction failure stop the build than find it in a diff of the output. It asks for something in return: styles are written one way, as objects passed to a call, and dynamic values have to be reachable statically or say so.
Styling engine
Bamboo integrates through Vite. Its compiler turns analyzable style calls into shared atomic CSS during the build, and fails when a class-producing call would survive to runtime.
import { css } from '../styled-system/css'
import { center, flex } from '../styled-system/patterns'
function App() {
return (
<div
className={flex({
direction: 'row',
gap: '8px',
p: '4',
rounded: 'md',
shadow: 'lg',
bg: 'white',
})}
>
<div className={center({ size: '5rem', borderRadius: 'full', overflow: 'hidden' })}>
<img src="https://via.placeholder.com/150" alt="avatar" />
</div>
<div className={css({ mt: '4', fontSize: 'xl', fontWeight: 'semibold' })}>John Doe</div>
<div className={css({ mt: '2', fontSize: 'sm', color: 'gray.600' })}>john@doe.com</div>
</div>
)
}
Token generator
Bamboo has first-class support for design tokens. It provides a way to express raw and semantic tokens for your project. The generator can be used to create a set of CSS variables for your design tokens.
bamboo.config.ts
export default defineConfig({
emitTokensOnly: true,
theme: {
tokens: {
colors: {
gray50: { value: '#F9FAFB' },
gray100: { value: '#F3F4F6' },
},
},
semanticTokens: {
colors: {
primary: { value: 'token(colors.gray50)' },
success: {
value: { _light: 'token(colors.green500)', _dark: 'token(colors.green200)' },
},
},
},
},
})Running the bamboo codegen will generate
styled-system/tokens/index.css
:where(:root, :host) {
--colors-gray50: #f9fafb;
--colors-gray100: #f3f4f6;
--colors-primary: var(--colors-gray50);
}
.light {
--colors-success: var(--colors-green500);
}
.dark {
--colors-success: var(--colors-green200);
}Then you have a set of css variables that you can use in your project.
@import '../styled-system/tokens/index.css';
.card {
background-color: var(--colors-gray50);
}
When not to use Bamboo?
Bamboo isn't the right fit for your project if:
- You're building with HTML and CSS.
- You're using a template-based framework like PHP.
- You're looking for an absolute zero JS solution.
In these scenarios, we recommend that you use vanilla CSS (which is getting awesome by the day), or other utility based CSS libraries.