Skip to content

Tailwind

In Next.js you add Tailwind by installing three packages, creating tailwind.config.js, adding the @tailwind directives to globals.css, and importing that file in _app.tsx. Astro ships an official integration that does all of that in one command.

Playground note: Tailwind requires its Vite integration to be installed in the project — a single-file .astro page in StackBlitz cannot load it without the full setup. This lesson is code-only. Copy any snippet to a local project created with npx create astro@latest and run the steps below to try it live.

Terminal window
# inside your Astro project
npx astro add tailwind

The CLI installs @astrojs/tailwind and tailwindcss, creates tailwind.config.mjs, and adds the integration to astro.config.mjs. Accept all prompts.

// astro.config.mjs — after running the command
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
export default defineConfig({
integrations: [tailwind()],
});
// tailwind.config.mjs — auto-generated
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{astro,html,js,jsx,ts,tsx,svelte,vue}'],
theme: { extend: {} },
plugins: [],
};

No globals.css import needed — the integration handles that automatically.

React
// Card.tsx (Next.js + Tailwind)
export default function Card({
title,
description,
featured = false,
}: {
title: string;
description: string;
featured?: boolean;
}) {
return (
<div className={`rounded-xl border p-6 shadow-sm ${
featured ? 'border-indigo-500 bg-indigo-50' : 'border-slate-200 bg-white'
}`}>
<h2 className="mb-2 text-lg font-semibold text-slate-900">{title}</h2>
<p className="text-sm text-slate-600">{description}</p>
</div>
);
}
Astro
---
// Card.astro (Astro + Tailwind)
interface Props { title: string; description: string; featured?: boolean; }
const { title, description, featured = false } = Astro.props;
---
<div class:list={[
"rounded-xl border p-6 shadow-sm",
featured ? "border-indigo-500 bg-indigo-50" : "border-slate-200 bg-white",
]}>
<h2 class="mb-2 text-lg font-semibold text-slate-900">{title}</h2>
<p class="text-sm text-slate-600">{description}</p>
</div>

The only mandatory change: className becomes class. Everything else — utility classes, responsive prefixes, dark-mode variants, arbitrary values — works identically.

You can use Tailwind utilities and a <style> block in the same .astro file. This is useful when a component needs a complex selector (e.g., nth-child, ::before) that Tailwind cannot express cleanly.

HeroSection.astro
<section class="py-24 px-6 bg-gradient-to-br from-indigo-600 to-purple-700">
<h1 class="text-4xl font-bold text-white mb-4">Ship faster</h1>
<p class="text-indigo-200 max-w-xl">Tailwind utilities + scoped styles in one component.</p>
</section>
<style>
/* Scoped rule for a complex selector Tailwind cannot express */
section > *:not(:last-child) { margin-bottom: 1rem; }
</style>

Tailwind and framework components (React / Vue inside Astro)

Section titled “Tailwind and framework components (React / Vue inside Astro)”

Utility classes also work on framework components rendered inside Astro pages. Pass classes as class on the Astro wrapper or as className inside JSX if you are inside a .tsx Island component.

Page.astro
---
import Counter from './Counter.tsx';
---
<!-- Tailwind class on the Astro element wrapper -->
<div class="max-w-screen-lg mx-auto px-4">
<!-- className inside the React Island -->
<Counter className="mt-8" client:visible />
</div>
What single command adds Tailwind to an Astro project and handles all configuration automatically?
In a `.astro` template you use Tailwind classes. Which attribute do you use?
After running `npx astro add tailwind`, do you need to manually import Tailwind's CSS in a layout file?