跪拜 Guibai
← All articles
Frontend · CSS · Vite

UnoCSS vs. Tailwind CSS v4: The Atomic CSS Engine War Reaches a Rust-Powered Stalemate

By Hex的极客茶水间 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

The performance argument that once made UnoCSS a clear winner over Tailwind v3 has largely evaporated with v4's Rust rewrite. Teams now choose based on whether they need JS-driven dynamic rule generation for a proprietary design system (UnoCSS) or instant compatibility with the Tailwind-first UI library ecosystem that dominates React and Vue projects. The real cost of switching is not build milliseconds but the debugging time spent on edge-case cascade conflicts when a preset emulates another framework's internal class-resolution logic.

Summary

Atomic CSS has moved through three generations: static pre-generation, JIT file-scanning, and now instant on-demand engines. UnoCSS, created by Vite core team member Anthony Fu, represents the third wave. It carries zero built-in utility classes, instead using pluggable presets to emulate Tailwind, Windi, or Bootstrap syntax while performing regex tokenization and hash-table lookups directly on Vite's memory stream — no AST, no PostCSS, no disk I/O.

Tailwind CSS v4 responded by abandoning PostCSS entirely for a Rust-powered Oxide engine and Lightning CSS, bringing its full-build times down to 6–8 ms. For most projects under 200 pages, the two are now perceptually identical. The real divergence appears in monorepos with tens of thousands of components, where UnoCSS's constant-time HMR (10–20 ms regardless of project size) outlasts Tailwind's filesystem-based incremental scanning, which can fluctuate between 100–500 ms under heavy concurrent edits.

Beyond raw speed, the tools split along a CSS-First versus JS/TS-First fault line. Tailwind v4 moved configuration into native CSS `@theme` directives, while UnoCSS keeps everything in `uno.config.ts`, enabling compile-time dynamic rule generation from APIs or business logic. UnoCSS also ships native variant groups, attributify mode, a compile-class transformer that hashes long class strings into short unique names, and a blocklist system that enforces team design-token standards at the regex level. Tailwind's moat remains its ecosystem: Shadcn/ui, DaisyUI, and Headless UI are built Tailwind-first, and subtle cascade-layer mismatches can still surface when UnoCSS's preset tries to emulate them.

Takeaways
UnoCSS performs no AST parsing and no filesystem scanning; it tokenizes source code with regex and resolves rules via hash-table lookups directly on Vite's in-memory transform stream.
Full UnoCSS builds complete in 1–3 ms, and HMR stays at 10–20 ms regardless of project size because the engine only processes the single dirty file Vite hands it.
Tailwind CSS v4 replaced its PostCSS pipeline with a Rust-based Oxide engine and Lightning CSS, cutting full builds to 6–8 ms and incremental HMR to sub-millisecond ranges for typical projects.
In monorepos with tens of thousands of components, Tailwind v4's filesystem-based incremental scanning can still hit 100–500 ms under concurrent edits, while UnoCSS's constant-time architecture shows no degradation.
UnoCSS ships with zero built-in utility classes; all styles come from pluggable presets, and the `preset-wind4` preset now defaults to the OKLCH color space with native CSS `@property` and `@supports` progressive enhancement.
Tailwind v4 moved all configuration into native CSS `@theme` directives, eliminating the JS config file; UnoCSS keeps configuration in `uno.config.ts`, enabling compile-time dynamic rule generation from Node.js code or external APIs.
UnoCSS's compile-class transformer (`@unocss/transformer-compile-class`) hashes long utility class strings like `text-sm font-bold hover:text-red` into a single short class name such as `uno-0qw2gr`, keeping production HTML clean.
The blocklist feature enforces design-system compliance by intercepting forbidden class patterns (e.g., any px-based spacing utility) at the regex level and surfacing custom error messages during development.
UnoCSS's `preset-wind4` is mutually exclusive with the legacy compatibility preset, signaling a hard break toward modern browser standards and dropping polyfills for older engines.
Tailwind's ecosystem lock-in through Shadcn/ui, DaisyUI, and Headless UI remains its strongest defense; UnoCSS's preset-based emulation can still produce subtle cascade-layer mismatches in Tailwind-first component libraries.
Conclusions

Tailwind v4's Rust rewrite neutralized the raw-speed narrative that had been UnoCSS's primary selling point, but it did so by adopting the same architectural insight UnoCSS pioneered: the build tool's transform pipeline is the right place to generate CSS, not a separate file watcher.

The CSS-First versus JS-First configuration split is not just ergonomic preference. Tailwind's CSS-native theming aligns with a future where browsers understand design tokens natively, while UnoCSS's JS configuration is a bet that enterprise design systems will always need programmatic, build-time logic that CSS alone cannot express.

UnoCSS's blocklist is an underappreciated governance feature. In large teams, the ability to reject `m-4px` with a custom lint message enforces design-token compliance at the engine level, something Tailwind's plugin system can approximate but not enforce as directly.

The compile-class transformer solves a real problem — class-name pollution in production HTML — but it also introduces a debugging indirection: the hashed class name in the browser inspector no longer maps back to the source utilities without tooling support.

Tailwind's ecosystem dominance means the practical switching cost is rarely about the CSS engine itself. It is about whether a team is willing to debug the 5% of edge cases where UnoCSS's Tailwind-compatibility preset diverges from the real thing in a third-party UI library's internal class-resolution logic.

UnoCSS's exploration of OXC integration suggests the next frontier is not faster CSS generation — both engines are already at the physical limit — but faster and more accurate class-name extraction from increasingly complex JSX/TSX syntax trees.

Concepts & terms
Atomic CSS
A styling approach where each CSS class does exactly one thing (e.g., `text-red`, `m-4`), and interfaces are built by composing many single-purpose classes in HTML rather than writing custom semantic class names and corresponding stylesheets.
JIT (Just-in-Time) engine
A CSS generation strategy that scans source code for actually-used utility classes and generates only those rules on the fly, rather than pre-generating a complete stylesheet and then purging unused classes during a production build.
AST-free compilation
UnoCSS's approach of bypassing Abstract Syntax Tree parsing entirely. Instead of parsing CSS or JavaScript into a tree structure, it uses regex tokenization to extract class names and hash-table lookups to resolve them into CSS, avoiding the CPU and memory cost of AST construction and traversal.
Preset
In UnoCSS, a pluggable module that defines the actual utility classes, rules, variants, and theme values. The engine itself ships empty; presets like `preset-uno` or `preset-wind4` supply the Tailwind-compatible class vocabulary.
OKLCH color space
A perceptually uniform color model that supports wide-gamut displays (P3, Rec.2020). Unlike sRGB-based systems, OKLCH ensures a color's perceived brightness stays consistent across different backgrounds, and it is now the default in both Tailwind v4 and UnoCSS's `preset-wind4`.
Compile-class transformer
An UnoCSS transformer that detects a `:uno:` prefix in class attributes, hashes the subsequent utility class string, and replaces it with a single short class name like `uno-0qw2gr` in the built HTML, reducing class-name clutter in production markup.
Blocklist
An UnoCSS configuration feature that rejects specific utility class patterns (exact strings, regex matches, or custom predicate functions) before they generate CSS, typically used to enforce design-system rules such as banning pixel-based spacing utilities in favor of rem units.
OXC (Oxidation Compiler)
A collection of high-performance Rust-based JavaScript/TypeScript tooling (Oxlint, Oxc-transform) that parses and analyzes code roughly 3x faster than SWC. UnoCSS is exploring OXC integration to replace its regex-based class-name extraction with proper AST analysis for complex syntax edge cases.
From the discussion
Featured comments
增量编译

unocss's best feature is that you can put the original atomic class name string into attributes <div m-10px></div>

Hex的极客茶水间

Yes, and variant group, which tailwindcss doesn't seem to have — both are really nice features.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗