Install Tailwind CSS in a New Project
A practical walkthrough of installing Tailwind CSS v4 in a new project — the npm package, the @import directive, content sources, and quick integration notes for Vite and Astro.
What you'll learn
- ✓How to install Tailwind CSS v4 with npm
- ✓What the new @import "tailwindcss" directive does
- ✓How content sources are detected automatically
- ✓How to build your CSS for development and production
- ✓Quick integration notes for Vite and Astro
Prerequisites
- •A basic understanding of npm and the command line
- •Familiarity with CSS — see What Is CSS?
- •Optional: What Is Tailwind? for background
Installing Tailwind used to involve a config file, a PostCSS plugin, and a bit of patience. Tailwind v4 simplified the whole setup to a single CSS import and a build command. This post walks through it from scratch.
If you have not read What Is Tailwind? yet, skim it first — this article assumes you know what utility classes are.
What you need
Before you start, make sure you have:
- Node.js 20 or newer. Check with
node -v. - npm, pnpm, or yarn. Any package manager works; examples use
npm. - A project folder. It can be plain HTML, Vite, Astro, Next.js, or whatever you like.
If you do not have a project yet, create one:
mkdir my-site
cd my-site
npm init -y
That gives you a package.json to install into.
Step 1: Install the package
Install Tailwind and the CLI as dev dependencies:
npm install -D tailwindcss @tailwindcss/cli
Two packages:
tailwindcss— the engine and utility set@tailwindcss/cli— the standalone command-line build tool
If you are using Vite, Astro, or Next.js, you will swap the CLI for a framework plugin later. The CLI is the simplest way to verify everything works first.
Step 2: Create your input CSS
Make a file at src/input.css:
@import "tailwindcss";
That single line replaces the three @tailwind directives from Tailwind v3. The @import pulls in the base reset, component layer, and utility classes in one shot.
You can add your own CSS below it:
@import "tailwindcss";
body {
font-family: system-ui, sans-serif;
}
Step 3: Add some markup
Create an index.html to style:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Tailwind test</title>
<link rel="stylesheet" href="./dist/output.css" />
</head>
<body class="bg-gray-50 text-gray-900">
<main class="mx-auto max-w-xl p-8">
<h1 class="text-3xl font-bold">Hello, Tailwind</h1>
<p class="mt-2 text-gray-600">
Utility classes, hot off the build.
</p>
</main>
</body>
</html>
The <link> points at the file we are about to build.
Step 4: Build the CSS
Run the CLI:
npx @tailwindcss/cli -i ./src/input.css -o ./dist/output.css --watch
Three flags:
-i— your input file-o— where to write the compiled CSS--watch— rebuild whenever a source file changes
Open index.html in a browser. You should see a styled heading on a light gray background. Edit a class, save, and the file rebuilds instantly.
For a one-shot production build, drop --watch and add --minify:
npx @tailwindcss/cli -i ./src/input.css -o ./dist/output.css --minify
The output should land around 10–20 KB for a small site.
Step 5: Wire it up as an npm script
Typing the full command gets old. Add scripts to package.json:
{
"scripts": {
"dev": "tailwindcss -i ./src/input.css -o ./dist/output.css --watch",
"build": "tailwindcss -i ./src/input.css -o ./dist/output.css --minify"
}
}
Now npm run dev starts the watcher and npm run build produces the minified bundle.
Try it yourself. Run npm run dev, then change text-3xl to text-5xl in your HTML. The output CSS rebuilds and the browser reload shows a much bigger heading. Now try an arbitrary value — text-[42px] — and confirm it works without configuration.
How content detection works
Tailwind v4 scans your project for class names automatically. By default it looks at files in your project root and most common source folders, ignoring node_modules and .gitignore patterns.
If you keep source files in unusual locations, you can be explicit in your CSS:
@import "tailwindcss";
@source "../legacy/templates/**/*.html";
The @source directive tells the engine where to look beyond the defaults. You rarely need it for new projects.
Customising your theme
The old tailwind.config.js is optional in v4. Tokens now live in CSS using @theme:
@import "tailwindcss";
@theme {
--color-brand-500: #4f46e5;
--color-brand-700: #3730a3;
--font-display: "Inter", sans-serif;
}
Now bg-brand-500, text-brand-700, and font-display are real classes. Tokens are CSS variables — you can reference them anywhere, including outside Tailwind utilities.
Using Tailwind with Vite
For a Vite project, swap the CLI for the official plugin:
npm install -D tailwindcss @tailwindcss/vite
Update vite.config.js:
import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
plugins: [tailwindcss()],
});
Import your CSS from your entry file:
// src/main.js
import "./input.css";
Vite picks up the rest. Hot-reload now works inside the dev server with no separate watcher.
Using Tailwind with Astro
Astro has a first-party integration:
npx astro add tailwind
That command installs the plugin, edits astro.config.mjs, and adds the global stylesheet. You can verify it added something like this to your config:
import { defineConfig } from "astro/config";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
vite: { plugins: [tailwindcss()] },
});
Drop utility classes into any .astro, .mdx, or framework component and they just work.
Common setup mistakes
A few traps that catch beginners:
- Forgetting the
<link>tag. No styled output usually means the HTML never loaded your compiled CSS file. - Running the build once and editing forever. Without
--watch(or a Vite-style plugin), new classes never get added to the bundle. - Pointing
-oat your input file. Output and input must be different files. The CLI will refuse, but the typo is easy to make. - Editing the compiled output. Tailwind regenerates it on every build. Always edit the input CSS.
- Class names built from strings. Tailwind scans for literal class names.
`text-${size}`is invisible to the scanner — write full strings or use a small lookup map.
Try it yourself. Add @theme to your input CSS with a custom --color-accent-500: #f97316;. Use bg-accent-500 somewhere in your HTML, run the build, and confirm the class appears in your compiled output. Then remove the use — the class should disappear on the next build.
A small test page
A complete starter to verify everything is wired up:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Setup check</title>
<link rel="stylesheet" href="./dist/output.css" />
</head>
<body class="min-h-screen bg-gradient-to-br from-indigo-50 to-white">
<main class="mx-auto max-w-md p-8">
<div class="rounded-xl bg-white p-6 shadow-md">
<h1 class="text-2xl font-bold text-gray-900">It works</h1>
<p class="mt-2 text-gray-600">
Edit a class and save — the page should update.
</p>
<button
class="mt-4 rounded-md bg-indigo-600 px-4 py-2 font-semibold text-white hover:bg-indigo-700"
>
A button
</button>
</div>
</main>
</body>
</html>
If the card has shadow, the heading is bold, and the button changes shade on hover, the install worked.
Recap
You now know:
- Tailwind v4 installs with two packages:
tailwindcssand@tailwindcss/cli - A single
@import "tailwindcss"replaces the older@tailwinddirectives - The CLI builds with
-i,-o,--watch, and--minify @themecustomises colors, fonts, and tokens in pure CSS- Vite and Astro have first-class plugins that replace the CLI
Next steps
With Tailwind installed, the next step is learning the layout utilities — flex, grid, spacing, and sizing — so you can build real pages instead of styling a single button.
Next: Tailwind Layout Utilities
Related: What Is Tailwind?, CSS Flexbox Basics, CSS Grid Basics.
Questions or feedback? Email codeloomdevv@gmail.com.