Plate 93
UnoCSS vs Tailwind: 10.5KB vs 18.5KB CSS
UnoCSS 66.5.2 (presetWind3) vs Tailwind CSS 4.1.13 (@tailwindcss/vite) on Vite 7.3.6: 80 HTML cards, same utility set, minify off. CSS 10,454 B (118 selectors) vs 18,473 B (119). Warm vite build medians (7 rounds, cache cleared): Uno 749 ms vs Tailwind 416 ms. Fixture /workspace/bench-unocss-tw/.
Aditya Challa4 min read
On 80 identical utility-class cards in a Vite 7 app, UnoCSS 66.5 emitted 10,454 bytes of CSS while Tailwind CSS v4.1 emitted 18,473 bytes for essentially the same selector count (118 vs 119). Warm production-build medians favored Tailwind: 416 ms against UnoCSS at 749 ms.
Short answer: pick UnoCSS when shipped CSS weight is the constraint; pick Tailwind v4 when build speed and the wider utility ecosystem matter more on a small page like this. No affiliate links in this post.
What I tested
- Machine: 8 vCPU Intel Xeon / 15 GB RAM shared Linux cloud box, tested 6 Oct 2026 about 00:14–00:15 IST.
- Versions: Vite 7.3.6, Tailwind CSS 4.1.13 with @tailwindcss/vite 4.1.13, UnoCSS 66.5.2 with presetWind3, Node 22.20.0. minify and cssMinify both off.
- Fixture: /workspace/bench-unocss-tw/. 80 HTML cards sharing one utility set (flex, gaps, colors, responsive grid, dark: variants). Matching index.tw.html / index.uno.html entrypoints.
- Timing: wall clock around local
vite buildper config. Dist and Vite cache cleared each round. One warm-up, then 7 interleaved timed rounds. CSS bytes and selector counts taken from dist assets. - Findings: CSS 10,454 B (Uno) vs 18,473 B (Tailwind), selectors 118 vs 119. Build medians 749 ms (Uno) vs 416 ms (Tailwind). Uno CSS about 43% smaller; Tailwind about 333 ms faster median.
- One surprise: selector counts nearly matched, yet Tailwind's stylesheet stayed ~8 KB heavier — mostly preflight / scaffolding, not extra utilities.
- Not tested: attributify mode, icons presets, codebases, Tailwind plugins, safelist explosion, SSR frameworks, Windows or macOS.
Who shipped less CSS?
| Engine (80 cards, minify off) | CSS bytes | Selectors | Vite build median |
|---|---|---|---|
| UnoCSS 66.5 + presetWind3 | 10,454 B | 118 | 749 ms |
| Tailwind CSS 4.1 + @tailwindcss/vite | 18,473 B | 119 | 416 ms |
Same class strings in HTML, same Vite major. UnoCSS won on payload; Tailwind won on wall time for this tiny graph (4 modules transformed). If your bottleneck is transfer size on a marketing page, the 8 KB gap is the headline. If your bottleneck is iterative vite build in CI, Tailwind was quicker here.
For adjacent CSS tooling on this site, see Lightning CSS vs PostCSS and the Tailwind CSS v4 migration checklist.
Is the build-time gap real?
On this fixture, yes: median 416 ms vs 749 ms after clearing dist and the Vite cache every round. Absolute times are small because the module graph is tiny. Do not extrapolate to a 2,000-file app without re-measuring. The useful bit is the direction: Tailwind's Oxide pipeline was the faster Vite plugin path for the same utility set.
Bundle size of the JS entry was identical (1.25 kB) because both builds only logged a querySelectorAll count. The decision is about CSS output and plugin cost, not JS.
Should you move from Tailwind to UnoCSS?
| Situation | My pick |
|---|---|
| Shipping a small public page where every KB counts | UnoCSS |
| Existing Tailwind design system / UI kit | Stay on Tailwind v4 |
| Need fastest Vite plugin build on a tiny graph | Tailwind (here) |
| Want attributify or icon presets in one stack | Evaluate UnoCSS |
| Already mid Tailwind v4 migration | Finish that path; see the v4 checklist |
| Comparing broader Vite tooling choices | Vite vs Parcel and Vite Plus toolchain notes |
Bottom line: UnoCSS cut CSS from 18.5 KB to 10.5 KB on the same 80 cards; Tailwind returned the green build about 333 ms sooner. Who should not switch: teams whose components, docs, and hiring already assume Tailwind class names.
How this was made: I built matching Vite configs for Tailwind v4 and UnoCSS on the ShopperCove box, cleared caches between seven interleaved production builds, compared CSS bytes and wall medians from JSON; the write-up was drafted with AI help and checked against that output.
Sources
- https://unocss.dev/
- https://tailwindcss.com/docs/installation/using-vite
- https://github.com/unocss/unocss
- https://github.com/tailwindlabs/tailwindcss
- https://vite.dev/
Related
- https://www.shoppercove.com/blog/tailwind-css-v4-migration-checklist-2026
- https://www.shoppercove.com/blog/lightningcss-vs-postcss
- https://www.shoppercove.com/blog/vite-vs-parcel
- https://www.shoppercove.com/blog/vite-plus-1-0-unified-toolchain-october-2026
- https://www.shoppercove.com/blog/vite-8-3-2-renderbuilturl-bundled-dev-sourcemaps-october-2026
- https://www.shoppercove.com/blog/rolldown-vs-rollup
- https://www.shoppercove.com/blog/size-limit-vs-bundlesize
- https://www.shoppercove.com/blog/biome-vs-eslint-prettier
Lab evidence
What I found running this
Hands-on on ShopperCove box 6 Oct 2026 ~00:14–00:15 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0). Vite 7.3.6, Tailwind 4.1.13 + @tailwindcss/vite 4.1.13, UnoCSS 66.5.2 presetWind3. Fixture /workspace/bench-unocss-tw/: 80 identical utility cards in HTML entrypoints; minify/cssMinify false. Local vite binary; dist + node_modules/.vite cleared each run; 1 warm-up + 7 interleaved rounds. CSS 10454 B / 118 selectors (Uno) vs 18473 B / 119 (Tailwind). Build medians 749 ms vs 416 ms. Raw: /workspace/bench-unocss-tw/res-unocss-tw.json. Not tested: attributify, icon presets, @apply-heavy apps, Tailwind plugins, SSR, Windows/macOS. No affiliate.
Related links
Plate 55
Klona vs structuredClone: 1.4M vs 225k Clones per Second
5 Oct 2026
Plate 66
Jotai vs Zustand: 0.15 ms vs 0.17 ms per Update
5 Oct 2026
Plate 60
Zustand vs Redux Toolkit: 0.14 ms vs 0.68 ms per Update
zustand 5.0.15 vs @reduxjs/toolkit 2.13.0 + react-redux 9.3.0 on React 19.3.0 (jsdom, NODE_ENV=production). 1,000 selector-subscribed rows, 300 flushSync updates x 7 trials, 2 runs: per-update median 0.137/0.139 ms vs 0.676/0.694 ms (~5x); 1 row re-rendered per update in both. Store-only: 1,376,191 vs 6,502 updates/s; Immer autoFreeze off lifts RTK to 386,966. Gzip (React external): 387 B vs 9,708 B. Fixture /workspace/bench-zustand-rtk/.
5 Oct 2026