ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 93

  1. Blog

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 Challa·5 October 2026·4 min read

Hands-on
On this page
  1. What I tested
  2. Who shipped less CSS?
  3. Is the build-time gap real?
  4. Should you move from Tailwind to UnoCSS?
  5. Sources
  6. Related

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 build per 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 bytesSelectorsVite build median
UnoCSS 66.5 + presetWind310,454 B118749 ms
Tailwind CSS 4.1 + @tailwindcss/vite18,473 B119416 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?

SituationMy pick
Shipping a small public page where every KB countsUnoCSS
Existing Tailwind design system / UI kitStay on Tailwind v4
Need fastest Vite plugin build on a tiny graphTailwind (here)
Want attributify or icon presets in one stackEvaluate UnoCSS
Already mid Tailwind v4 migrationFinish 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
unocsstailwindcssvitecss-performanceweb-developmentbuild-toolsbundle-sizebenchmarking

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.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

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

On this page

  1. What I tested
  2. Who shipped less CSS?
  3. Is the build-time gap real?
  4. Should you move from Tailwind to UnoCSS?
  5. Sources
  6. Related
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove