Zero Runtime
Static sz props compile to string literals. Nothing runs in the browser for the common case.
CSSzyx is a CSS-in-JS framework that compiles object-syntax Tailwind props to
plain className strings at build time. An opt-in production step can then
mangle those strings to hide the utility vocabulary — an obfuscation feature,
not a size one: over a gzip-served app the arithmetic comes out flat or slightly
negative, and the build reports the measured delta.
Traditional Tailwind usage has sharp edges:
// ❌ No type safety — typos silently produce no styles<div className="p-4 bg-red-500 hover:bg-blue-600" />
// ❌ String concatenation is fragile<div className={`p-4 ${isActive ? 'bg-blue-500' : 'bg-gray-200'} ${extraClass}`} />CSSzyx solves this with object syntax:
// ✅ TypeScript catches invalid values at compile time<div sz={{ p: 4, bg: 'red-500', hover: { bg: 'blue-600' } }} />
// ✅ Conditionals are natural JavaScript<div sz={{ p: 4, bg: isActive ? 'blue-500' : 'gray-200' }} />Pre-scan — Walk source files at startup, write .csszyx/csszyx-classes.txt so
Tailwind JIT can discover every sz-generated class name before compilation begins.
JSX Transform — sz={{ p: 4, hover: { bg: 'blue-500' } }} → className="p-4 hover:bg-blue-500" (native engine).
Also injects the @source directive into your CSS entry and auto-imports
csszyx/lite runtime helpers where needed.
Tailwind JIT — Reads .csszyx/csszyx-classes.txt, scans transformed className
strings, generates CSS for every class in the build.
Mangle (opt-in, production.mangle) — Builds the encode map p-4 → z,
bg-blue-500 → y … using reversed tier-based encoding, then computes a
SHA-256 checksum of the full map.
Emit — Mangles CSS selectors and JS class strings in all output assets, then injects the checksum and mangle map into the HTML document.
Each phase is incremental. During dev, HMR updates .csszyx/csszyx-classes.txt when new
sz props are added — no server restart needed.
The safelist is plain text, one class per line: Tailwind’s scanner reads any file
as bytes, and parent-child CSS such as space-y-* or [&>span]:* comes from the
class name, not from markup around it. With the Vite plugin, a safelist write is
not a file the dev server can match to a module on its own, so csszyx tells it
which modules the write affects — your Tailwind entry stylesheets, since they
@source the file — and a class the project has never used before arrives as a
CSS hot update. Component state, scroll position and open dialogs survive.
Zero Runtime
Static sz props compile to string literals. Nothing runs in the browser for the common case.
Type Safe
Auto-generated types from your Tailwind config. Invalid values are TypeScript errors, not silent bugs.
SSR Safety
SHA-256 checksums verify the mangle map matches between server and client. Mismatch triggers the abort protocol.
With production.mangle on (it is off by default), every Tailwind class is
replaced by a short encoded symbol using reversed tier-based encoding
(z → y → x → ...). The point is that the utility vocabulary is not readable
in the shipped markup; it is not a smaller payload — see
the caution in the config reference.
<!-- Development build --><div class="p-4 bg-blue-500 hover:bg-blue-600 rounded-lg text-white">
<!-- Production build --><div class="z y x a b">The mangle map (z → p-4, y → bg-blue-500, …) is embedded in the HTML
along with a SHA-256 checksum. The client runtime verifies this before
hydrating.
The hot paths (encoding, checksum, collision detection) are implemented in Rust and compiled to WASM for performance. The compiler and runtime remain TypeScript for fast iteration.
CSSzyx targets Tailwind CSS v4 only. Tailwind v3 support is planned for a future release after the core is stable.