How it works
Mental model
- Authoring — Semantic classes in CSS (
.card { … }) and staticclassName/cn()/clsx()in JSX. - Extraction (Rust) — Lightning CSS parses the sheet; shorthands expand to longhands; each declaration becomes a hashed atom (same property + value + context → same class).
- Bundler (Vite) — CSS is collected from
cssglobs (and/or the Vite graph when globs are empty), extracted, and injected asvirtual:driftcss. JSX is rewritten viaresolveClassesusing rule order (rule_index). - Runtime — No CSS parser in the browser; only class strings change.
Pipeline
flowchart LR
subgraph inputs [Inputs]
CSS[Author CSS]
TSX[TSX/JSX]
end
subgraph vite ["@driftcss/vite"]
Collect[Collect CSS]
Rewrite[JSX rewrite]
end
subgraph rust [Rust core]
Parse[Lightning CSS parse]
Extract[Extract atoms + mapping]
Merge[Merge resolver]
end
subgraph outputs [Build outputs]
AtomsCSS[virtual:driftcss]
Map["driftcss-map.json on vite build"]
TSXOut[Rewritten classNames]
end
CSS --> Collect --> Parse --> Extract
Extract --> AtomsCSS
Extract --> Map
Extract --> Merge
TSX --> Rewrite --> Merge --> TSXOutDev extracts each CSS file (disk-cached) and merges the payloads. Production compact names (c-0, c-1, …) run one extract on the merged sheet so ids stay unique.
Example
.border { border-color: red; border-style: solid; } expands to side longhands and becomes multiple c-* atoms. .box with the same border-top-color: red reuses the same atom in CSS and HTML.
Pass-through rules
Not every rule is atomized. Global selectors (body {}) and combinators are serialized in source order. Top-level @media { .x { } } is atomized. @layer / @starting-style serialize the block — classes inside are not atomized. See Coverage.
Interactive demo
The home page has a live extract model: edit CSS, see expanded atoms and the rewritten className. It is a client-side illustration (flat selectors only) — nested / combinator CSS will not match a real extractFull run. The Rust compiler runs at build time.
Install path: Using Vite. You can also run the example app from a clone of this repo:
pnpm build:example