UnoCSS: The Fastest On-Demand Atomic CSS Engine
TOP 5 March 9, 2026, 11:30 a.m.

UnoCSS: The Fastest On-Demand Atomic CSS Engine

UnoCSS has been turning heads in the front‑end community for its lightning‑fast, on‑demand generation of atomic CSS utilities. Unlike traditional utility‑first frameworks that ship a massive stylesheet, UnoCSS compiles only the classes you actually use, right at build time or even at runtime. This approach slashes bundle size, speeds up page loads, and keeps your development experience snappy. In this article we’ll dive deep into how UnoCSS works, walk through real‑world setups, and share pro tips to squeeze every bit of performance out of it.

What Makes UnoCSS Different?

At its core, UnoCSS is an on‑demand atomic CSS engine. It parses your source files, extracts class names, and generates the corresponding CSS rules on the fly. Because the engine never generates unused utilities, the final CSS payload can be as small as a few kilobytes for a typical SPA.

UnoCSS also embraces a config‑first philosophy. You define your design tokens—colors, spacing, fonts—in a single configuration object, and the engine expands them into utilities automatically. This eliminates the need to maintain a sprawling stylesheet or manually write custom classes.

On‑Demand vs. Pre‑Generated

  • Pre‑generated (e.g., Tailwind): ships a static CSS file containing every possible utility.
  • On‑demand (UnoCSS): builds only what you reference, reducing CSS bloat dramatically.

The on‑demand model also means you can add new utilities without rebuilding the entire stylesheet. This is a game‑changer for large teams that frequently iterate on design systems.

Getting Started: Installation & Basic Setup

UnoCSS can be used as a Vite, Webpack, or Rollup plugin, but the simplest entry point is the Vite plugin. Run the following command in your project root:

npm install -D @unocss/vite

Next, create an unocss.config.ts (or .js) file at the project root. Below is a minimal configuration that defines a custom color palette and a few shortcuts.

import { defineConfig, presetUno, presetAttributify } from 'unocss'

export default defineConfig({
  presets: [
    presetUno(),
    presetAttributify(),
  ],
  theme: {
    colors: {
      primary: '#1e40af',
      secondary: '#64748b',
    },
  },
  shortcuts: {
    // reusable class groups
    'btn-primary': 'px-4 py-2 rounded bg-primary text-white hover:bg-primary/80',
    'card': 'p-4 rounded-lg shadow-md bg-white',
  },
})

Finally, add the plugin to your vite.config.ts:

import { defineConfig } from 'vite'
import UnoCSS from '@unocss/vite'

export default defineConfig({
  plugins: [UnoCSS()],
})

That’s it—start your dev server and you can immediately use atomic classes like bg-primary, p-2, or the shortcut btn-primary in your markup.

Writing Atomic Classes: The Everyday Workflow

UnoCSS follows the same utility naming conventions you’ll recognize from Tailwind, but with a few extra tricks. For instance, you can combine arbitrary values directly in the class name using square brackets.

Example: bg-[#ff5722] applies a custom background color without touching the config file. Similarly, text-[clamp(1rem,2vw,2rem)] lets you inject responsive CSS functions on the fly.

Responsive & State Variants

Responsive prefixes (sm:, md:, lg:) and state modifiers (hover:, focus:) work out of the box. Because UnoCSS parses the class string at compile time, you can chain them arbitrarily.

<button class="btn-primary md:btn-primary-lg hover:shadow-lg">
  Click me
</button>

In the snippet above, the button uses the btn-primary shortcut on small screens and a larger variant on medium screens, while adding a hover shadow.

Advanced Usage: Dynamic Classes & Shortcuts

One of UnoCSS’s most powerful features is the ability to generate classes dynamically based on runtime data. This is especially handy when you need to apply a color from a user‑defined palette.

Using the dynamic shortcut, you can map a placeholder to a value at render time. Below is a Vue 3 component that demonstrates this pattern.

<template>
  <div :class="`bg-${color} text-white p-4 rounded`">
    Dynamic background!
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const color = ref('primary') // could be 'secondary', 'emerald', etc.
</script>

Because UnoCSS scans the template during the build, it will generate bg-primary, bg-secondary, and any other referenced colors automatically.

Custom Rules for Arbitrary Patterns

If you need a utility that isn’t covered by the default presets, you can define a custom rule. The rule receives the matched class name and returns a CSS declaration.

import { defineConfig, presetUno } from 'unocss'

export default defineConfig({
  presets: [presetUno()],
  rules: [
    // matches `rotate-45`, `rotate-90`, etc.
    [/^rotate-(\d+)$/, ([, deg]) => ({
      transform: `rotate(${deg}deg)`,
    })],
  ],
})

Now you can write rotate-45 directly in your markup, and UnoCSS will output the appropriate transform rule.

Pro Tip: Keep custom rules in a separate file (e.g., uno.rules.ts) and import them into your main config. This keeps the config tidy and makes sharing rules across projects a breeze.

Performance Benchmarks: Why “Fastest”?

UnoCSS’s speed stems from three core optimizations: a lightweight parser, a just‑in‑time (JIT) generation pipeline, and aggressive caching. In a recent benchmark on a 30‑page React app, the CSS bundle dropped from 210 KB (Tailwind JIT) to under 12 KB with UnoCSS, while build time improved by 45%.

Another advantage is the incremental build support. During development, only files that changed trigger a re‑generation of the affected utilities, keeping hot‑module replacement (HMR) almost instantaneous.

Measuring Impact in Your Project

  1. Run npm run build with UNOCSS_DEBUG=1 to see a list of generated classes.
  2. Check the final CSS size in the dist folder.
  3. Compare load times using Chrome DevTools' “Network” panel.

Most developers report a noticeable reduction in first‑contentful‑paint (FCP) after switching to UnoCSS, especially on mobile devices with slower connections.

Real‑World Use Cases

Component Libraries – When building a design system, you often need a consistent set of utilities across many components. UnoCSS’s shortcuts let you define component‑level class bundles (e.g., card, modal) that stay in sync with the theme.

Content‑Heavy Sites – Blogs and documentation sites benefit from the on‑demand model because the variety of classes is limited to the content actually rendered. This keeps the CSS footprint minimal without sacrificing flexibility.

Micro‑Frontends – In a micro‑frontend architecture, each team can ship its own UnoCSS config. Since the engine merges configs at build time, there’s no risk of class collisions, and each bundle only includes the utilities it needs.

Integrating UnoCSS with Popular Frameworks

Vue 3

Vue’s single‑file components (SFCs) are a perfect match for UnoCSS because the parser can read the <template> section directly. Install the Vite plugin as shown earlier, and you’re ready to go.

React

In React, you typically use JSX, which UnoCSS can parse with the @unocss/babel-preset. Add the preset to your Babel configuration:

{
  "presets": ["@unocss/babel-preset"]
}

Now any class string inside JSX will be processed. For dynamic class names, remember to keep the possible values discoverable at compile time (e.g., by using an enum).

Svelte

Svelte’s compiler already extracts class attributes, so you only need the Vite plugin. UnoCSS will generate CSS during the Svelte compilation step, ensuring the final bundle stays lean.

Comparison with Other Atomic CSS Engines

While Tailwind’s JIT mode and WindiCSS also generate utilities on demand, UnoCSS distinguishes itself with a smaller core (≈8 KB gzipped) and a more extensible rule system. Tailwind relies heavily on a massive default config, whereas UnoCSS encourages you to start minimal and grow only what you need.

Another differentiator is the attribute mode (via presetAttributify), which lets you write utilities as HTML attributes (bg="primary")—a pattern that reduces visual noise in complex components.

Pro Tip: When migrating from Tailwind, start by importing presetWind into UnoCSS. This preset mimics Tailwind’s class names, letting you transition gradually while still gaining the on‑demand benefits.

Best Practices & Pro Tips

  • Keep the config small. Only declare the scales (colors, spacing) you actually use. This encourages a more deliberate design system.
  • Leverage shortcuts. Group frequently used class combos into a single name to improve readability.
  • Use attribute mode for complex components. It separates styling concerns from content and makes the markup cleaner.
  • Enable caching in CI. UnoCSS supports a cacheDir option; persisting the cache across builds speeds up subsequent runs.
  • Audit generated CSS. Run UNOCSS_DEBUG=1 npx unocss periodically to ensure no stray classes are leaking.

By following these guidelines, you’ll get the most out of UnoCSS’s performance gains while keeping your codebase maintainable.

Conclusion

UnoCSS proves that on‑demand atomic CSS isn’t just a buzzword—it’s a practical, measurable improvement for modern web projects. Its tiny runtime, flexible configuration, and seamless integration with major frameworks make it a compelling alternative to traditional utility‑first libraries. Whether you’re building a massive design system or a simple blog, UnoCSS can shrink your CSS payload, accelerate builds, and keep your development workflow delightful.

Share this article