/ astro-integrations / How to Integrate UnoCSS with Astro: Complete Guide
astro-integrations 5 min read

How to Integrate UnoCSS with Astro: Complete Guide

Step-by-step guide to integrating UnoCSS with your Astro website.

UnoCSS is an atomic CSS engine that is instant and on-demand. It generates only the CSS you use, with zero parsing of your stylesheets. If you have used Tailwind CSS, UnoCSS will feel familiar, but it is fundamentally different under the hood. Instead of scanning your code for predefined utility classes, UnoCSS uses a rules engine that can match any pattern you define.

The result is faster builds, smaller CSS output, and extreme flexibility. You can use Tailwind-compatible syntax, Windi CSS syntax, or define completely custom utility patterns. For Astro sites, UnoCSS integrates directly into the build process through a Vite plugin.

Prerequisites

  • Node.js 18+
  • An Astro project (npm create astro@latest)

Installation

Install UnoCSS and the Astro integration:

npm install -D unocss @unocss/astro

Configuration

Add UnoCSS to your astro.config.mjs:

import { defineConfig } from "astro/config";
import UnoCSS from "@unocss/astro";

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

Create a uno.config.ts in your project root:

// uno.config.ts
import {
  defineConfig,
  presetUno,
  presetAttributify,
  presetIcons,
  presetTypography,
  transformerDirectives,
  transformerVariantGroup,
} from "unocss";

export default defineConfig({
  presets: [
    presetUno(), // Tailwind/Windi CSS compatible utilities
    presetAttributify(), // Attributify mode (optional)
    presetIcons({ scale: 1.2 }), // Icon support (optional)
    presetTypography(), // Prose styles (optional)
  ],
  transformers: [
    transformerDirectives(), // @apply support
    transformerVariantGroup(), // hover:(bg-red text-white)
  ],
  theme: {
    colors: {
      primary: {
        50: "#f0f9ff",
        100: "#e0f2fe",
        500: "#0ea5e9",
        600: "#0284c7",
        700: "#0369a1",
        900: "#0c4a6e",
      },
    },
    fontFamily: {
      sans: ["Inter", "sans-serif"],
      mono: ["JetBrains Mono", "monospace"],
    },
  },
  shortcuts: {
    btn: "px-4 py-2 rounded-lg font-medium transition-colors",
    "btn-primary": "btn bg-primary-500 text-white hover:bg-primary-600",
    "btn-outline":
      "btn border border-gray-300 hover:border-primary-500 hover:text-primary-500",
    container: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8",
  },
});

Import UnoCSS in your main layout:

---
// src/layouts/BaseLayout.astro
import "uno.css";
---

<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  </head>
  <body>
    <slot />
  </body>
</html>

Basic Usage

Use utility classes just like Tailwind CSS:

---
// src/components/Card.astro
export interface Props {
  title: string;
  description: string;
}

const { title, description } = Astro.props;
---

<div class="bg-white rounded-xl shadow-md p-6 hover:shadow-lg transition-shadow">
  <h3 class="text-xl font-bold text-gray-900 mb-2">{title}</h3>
  <p class="text-gray-600 leading-relaxed">{description}</p>
  <a href="#" class="btn-primary inline-block mt-4">Learn More</a>
</div>

Attributify Mode

The attributify preset lets you split classes into HTML attributes for cleaner markup:

<div
  bg="white"
  rounded="xl"
  shadow="md hover:lg"
  p="6"
  transition="shadow"
>
  <h3 text="xl gray-900" font="bold" mb="2">Title</h3>
  <p text="gray-600" leading="relaxed">Description</p>
</div>

This produces the same CSS but keeps your HTML more readable when you have many utilities.

Variant Groups

The variant group transformer lets you group utilities under a shared variant:

<!-- Without variant groups -->
<div class="hover:bg-blue-500 hover:text-white hover:shadow-lg hover:scale-105">
  Hover me
</div>

<!-- With variant groups -->
<div class="hover:(bg-blue-500 text-white shadow-lg scale-105)">
  Hover me
</div>

Icons with UnoCSS

The icons preset lets you use any icon from Iconify directly as CSS classes:

npm install -D @iconify-json/heroicons @iconify-json/lucide
<!-- Use icons as classes -->
<span class="i-heroicons-home w-6 h-6"></span>
<span class="i-lucide-search w-5 h-5 text-gray-400"></span>
<span class="i-heroicons-moon w-5 h-5 dark:i-heroicons-sun"></span>

No icon component libraries, no SVG imports. UnoCSS generates the icon as a CSS mask image.

Custom Rules

Define your own utility patterns:

// uno.config.ts
export default defineConfig({
  rules: [
    // Custom utility: text-balance
    ["text-balance", { "text-wrap": "balance" }],
    // Custom utility: content-grid
    [
      "content-grid",
      {
        display: "grid",
        "grid-template-columns":
          "[full-start] 1fr [content-start] min(65ch, 100%) [content-end] 1fr [full-end]",
      },
    ],
  ],
});

Use them like any other utility:

<div class="rounded-xl p-6">
  <p class="text-balance">This text wraps more evenly across lines.</p>
</div>

Dark Mode

UnoCSS supports dark mode with the same dark: prefix:

<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
  <h1 class="text-primary-600 dark:text-primary-400">
    Works in both modes
  </h1>
</div>

Production Tips

  1. Use shortcuts for repeated patterns. Instead of writing px-4 py-2 rounded-lg font-medium on every button, define a btn shortcut in your config. This keeps your HTML clean and makes design changes easier.

  2. Check the generated CSS. Run npx unocss to see what CSS UnoCSS generates. This helps you catch unused rules and verify that your custom patterns produce the correct output.

  3. Combine presets strategically. Start with presetUno() for Tailwind compatibility. Add presetIcons() only if you use CSS icons. Add presetTypography() only if you need prose styles. Each preset adds to the processing time.

  4. Use safelist for dynamic classes. If you generate class names dynamically, add them to the safelist in your config so UnoCSS includes them in the output.

  5. Migrate from Tailwind gradually. UnoCSS is compatible with most Tailwind utilities. You can switch your build from Tailwind to UnoCSS and most of your existing classes will work without changes.

Alternatives to Consider

  • Tailwind CSS if you prefer a larger ecosystem with more community plugins and official component libraries.
  • Windi CSS (now deprecated) was the predecessor. Its ideas live on in UnoCSS.
  • Open Props if you prefer CSS custom properties over utility classes.

Wrapping Up

UnoCSS brings the utility-first approach to a new level of performance and flexibility. For Astro sites, the integration is seamless through the Vite plugin, build times are noticeably faster than Tailwind, and the generated CSS is as small as it gets. The custom rules engine means you are never limited to predefined utilities. If you want atomic CSS with room to grow, UnoCSS is the engine to build on.