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
Use shortcuts for repeated patterns. Instead of writing
px-4 py-2 rounded-lg font-mediumon every button, define abtnshortcut in your config. This keeps your HTML clean and makes design changes easier.Check the generated CSS. Run
npx unocssto see what CSS UnoCSS generates. This helps you catch unused rules and verify that your custom patterns produce the correct output.Combine presets strategically. Start with
presetUno()for Tailwind compatibility. AddpresetIcons()only if you use CSS icons. AddpresetTypography()only if you need prose styles. Each preset adds to the processing time.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.
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.
Related Articles
How to Use Algolia with Astro: Complete Guide
Step-by-step guide to integrating Algolia with your Astro website.
How to Integrate Auth0 with Astro: Complete Guide
Step-by-step guide to integrating Auth0 with your Astro website. Setup, configuration, and best practices.
How to Use AWS Amplify with Astro: Complete Guide
Step-by-step guide to integrating AWS Amplify with your Astro website.