See all posts

How to Set Up Tailwind CSS in React

How to Set Up Tailwind CSS in React

Tailwind CSS In React

You're starting a new React project and want to style it fast. You've heard about Tailwind CSS, but the setup process looks confusing. Should you use Create React App or Vite? Why does everyone keep saying CRA is outdated? I'm going to show you the modern way to set up Tailwind CSS with React in 2025. I'll cover both methods, explain why Vite is better, and walk you through building an actual component so you can see everything working.

Table of Content

Why Vite Instead of Create React App?

Let me be direct: Tailwind officially recommends using Vite, Next.js, Remix, or Parcel instead of Create React App. Here's why that matters.

Vite is faster. Way faster. When you save a file, Vite offers blazing-fast Hot Module Replacement (HMR) and optimized builds. You'll see changes in milliseconds instead of waiting 2-3 seconds like with Create React App.

Create React App has limitations. CRA doesn't support custom PostCSS configurations and is incompatible with many important tools in the PostCSS ecosystem. This becomes a problem when you want to add plugins or customize how Tailwind generates styles.

Vite is what the community uses now. When you search for tutorials or ask for help in 2025, most developers will assume you're using Vite. It's the standard. I'll show you both methods, but if you're starting fresh, go with Vite. You'll thank yourself later.

Prerequisites

Before we start, make sure you have:

  • Node.js (version 18 or newer) - Download from nodejs.org. Node.js 18 reaches its EOL at the end of April 2025, so upgrading to Node.js 20 LTS or newer is recommended.

Check your version by opening your terminal and running:

bash
node --version

If it shows v18 or higher, you're good. If not, download the latest LTS version.

  • npm (comes with Node.js) - This installs automatically when you install Node.js.

  • A code editor - VS Code is popular and free. Download it from here

  • Basic React knowledge - You should understand components, props, and JSX. If not, read React's official tutorial first.

That's it. Let's build something.

This is the modern approach. You'll have a project running in under 5 minutes.

Step 1: Create Your React Project with Vite

Open your terminal and run:

bash
npm create vite@latest my-react-app

You'll see some prompts. Here's what to choose:

  1. Select a framework: Use arrow keys to select React, then press Enter
  2. Select a variant: Choose JavaScript (or TypeScript if you prefer)

Now move into your project folder and install dependencies:

bash
cd my-react-app
npm install

This sets up a React project with Vite. Much faster than Create React App, and you'll notice the difference immediately.

Step 2: Install Tailwind CSS Still in your terminal, run:

bash
npm install -D tailwindcss postcss autoprefixer

This installs three packages:

  • tailwindcss: The framework itself
  • postcss: Processes your CSS
  • autoprefixer: Adds browser prefixes automatically (like -webkit- for Safari)

Now create your config files:

bash
npx tailwindcss init -p

This creates two files in your project root: tailwind.config.js and postcss.config.js. Pro tip: Sometimes the init command causes errors. If that happens, just create the files manually. I'll show you exactly what goes in them.

Step 3: Configure Tailwind to Scan Your Files Open tailwind.config.js. Replace everything with this:

js
/** @type {import('tailwindcss').Config} */
export default {
content: ["./index.html", "./src/**/*.{js,jsx,ts,tsx}"],
theme: {
extend: {},
},
plugins: [],
};

The content array tells Tailwind where to look for class names. It'll scan these files and only generate CSS for the classes you actually use. This keeps your final CSS file small. The patterns break down like this:

  • ./index.html - Your main HTML file
  • ./src/**/*.{js,jsx,ts,tsx} - All JavaScript/TypeScript files in the src folder and subfolders

Step 4: Check Your PostCSS Config

Open postcss.config.js. It should look like this:

js
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

If it doesn't exist or looks different, create it with exactly this content. This tells PostCSS to process your CSS with Tailwind first, then Autoprefixer.

Step 5: Add Tailwind to Your CSS

Open src/index.css. Delete everything in there and replace it with:

css
@tailwind base;
@tailwind components;
@tailwind utilities;

These three lines import:

  • base - Resets and base styles (like normalized margins)
  • components - Class-based component styles (like buttons)
  • utilities - All the utility classes (like flex, bg-blue-500)

Make sure this file is imported in src/main.jsx (or main.tsx). You should see this line at the top:

js
import "./index.css";

If it's not there, add it.

Step 6: Test Everything Works

Let's make sure Tailwind is working. Open src/App.jsx and replace everything with:

jsx
function App() {
return (
<div className="flex items-center justify-center h-screen bg-linear-to-r from-blue-500 to-purple-600">
<div className="bg-white rounded-2xl shadow-2xl p-8 max-w-md">
<h1 className="text-4xl font-bold text-gray-900 mb-4">It Works! 🎉</h1>
<p className="text-gray-600 text-lg">
Tailwind CSS is running perfectly in your React + Vite project.
</p>
</div>
</div>
);
}
export default App;

Now start your dev server:

bash
npm run dev

Open your browser to http://localhost:5173 (Vite's default port). You should see a centered white card with colorful gradient background. If you see styled content, congratulations! Tailwind is working.

Preview

It Works! 🎉

Tailwind CSS is running perfectly in your React + Vite project.

Method 2: Create React App + Tailwind (Legacy Method)

I'm including this because some teams still use Create React App, or you might be adding Tailwind to an existing CRA project. But remember: Tailwind highly recommends using Vite, Parcel, Next.js, or Remix instead.

Step 1: Create React App

If you don't have a project yet:

bash
npx create-react-app my-tailwind-app
cd my-tailwind-app

This takes longer than Vite. You'll wait 2-3 minutes while it installs everything.

Step 2: Install Tailwind CSS

bash
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Same packages as before.

Step 3: Configure Tailwind Open tailwind.config.js and update it:

js
module.exports = {
content: ["./src/**/*.{js,jsx,ts,tsx}"],
theme: {
extend: {},
},
plugins: [],
};

Notice the difference from Vite: we don't include index.html because CRA handles it differently.

Step 4: PostCSS Config Your postcss.config.js should look like:

js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

Step 5: Add Tailwind Directives

Open src/index.css and add at the top (or replace everything):

css
@tailwind base;
@tailwind components;
@tailwind utilities;

Step 6: Test It

Replace src/App.js with:

jsx
function App() {
return (
<div className="flex items-center justify-center h-screen bg-blue-500">
<h1 className="text-4xl font-bold text-white">
Tailwind CSS with Create React App
</h1>
</div>
);
}
export default App;

Start the server:

bash
npm start

It'll open http://localhost:3000 automatically. You should see white text on a blue background.

Note: CRA is slower. Every time you save a file, you'll wait 1-2 seconds. With Vite, changes appear instantly.

Testing It Out: Build a Real Component

Let's build something more interesting than "Hello World." We'll create a profile card that looks professional.

Open your App.jsx (or App.js) and replace it with this:

js
function App() {
return (
<section className="flex items-center justify-center min-h-screen bg-linear-to-br from-purple-600 via-purple-500 to-indigo-600 p-4">
<div className="w-full max-w-md bg-white rounded-2xl shadow-2xl overflow-hidden">
{/* Card Header */}
<div className="px-6 py-8 bg-linear-to-r from-purple-600 to-indigo-600">
<h2 className="text-2xl font-bold text-white text-center mb-2">
Tailwind CSS
</h2>
<p className="text-purple-100 text-center italic">
"A utility-first CSS framework for rapid UI development"
</p>
</div>
{/* Card Body */}
<div className="p-6">
<div className="flex items-center space-x-4">
{/* Logo */}
<div className="shrink-0">
<div className="w-16 h-16 bg-linear-to-br from-cyan-400 to-blue-500 rounded-full flex items-center justify-center shadow-lg">
<svg
className="w-10 h-10"
fill="white"
viewBox="0 0 256 154"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M128 0C93.867 0 72.533 17.067 64 51.2 76.8 34.133 91.733 27.733 108.8 32c9.737 2.434 16.697 9.499 24.401 17.318C145.751 62.057 160.275 76.8 192 76.8c34.133 0 55.467-17.067 64-51.2-12.8 17.067-27.733 23.467-44.8 19.2-9.737-2.434-16.697-9.499-24.401-17.318C174.249 14.743 159.725 0 128 0zM64 76.8C29.867 76.8 8.533 93.867 0 128c12.8-17.067 27.733-23.467 44.8-19.2 9.737 2.434 16.697 9.499 24.401 17.318C81.751 138.857 96.275 153.6 128 153.6c34.133 0 55.467-17.067 64-51.2-12.8 17.067-27.733 23.467-44.8 19.2-9.737-2.434-16.697-9.499-24.401-17.318C110.249 91.543 95.725 76.8 64 76.8z" />
</svg>
</div>
</div>
{/* Creator Info */}
<div className="flex-1">
<p className="text-sm text-gray-500 font-medium">Created by</p>
<p className="text-xl font-bold text-gray-900">Adam Wathan</p>
</div>
</div>
{/* Stats Section */}
<div className="mt-6 grid grid-cols-3 gap-4 text-center">
<div className="bg-purple-50 rounded-lg p-3">
<p className="text-2xl font-bold text-purple-600">500K+</p>
<p className="text-xs text-gray-600">Downloads</p>
</div>
<div className="bg-indigo-50 rounded-lg p-3">
<p className="text-2xl font-bold text-indigo-600">70K+</p>
<p className="text-xs text-gray-600">GitHub Stars</p>
</div>
<div className="bg-blue-50 rounded-lg p-3">
<p className="text-2xl font-bold text-blue-600">300+</p>
<p className="text-xs text-gray-600">Contributors</p>
</div>
</div>
{/* Action Button */}
<button className="w-full mt-6 bg-linear-to-r from-purple-600 to-indigo-600 text-white font-semibold py-3 rounded-lg hover:shadow-lg hover:scale-105 transition-all duration-200">
Get Started
</button>
</div>
</div>
</section>
)
}
export default App

Save the file and look at your browser. You should see a gorgeous profile card with:

  • Gradient backgrounds
  • A centered Tailwind logo
  • Stats grid
  • Interactive button that scales on hover

This shows off what makes Tailwind powerful. You built a complete, professional-looking component without writing a single line of custom CSS. Every style came from utility classes. Try hovering over the button. Notice the smooth animation? That's from transition-all duration-200 combined with hover:shadow-lg hover:scale-105. These utilities make animations dead simple.

Preview

Tailwind CSS

"A utility-first CSS framework for rapid UI development"

Created by

Adam Wathan

500K+

Downloads

70K+

GitHub Stars

300+

Contributors

Customizing Your Tailwind Setup

The default Tailwind theme is great, but you'll want to customize it eventually. Here's how.

Adding Custom Colors

Open tailwind.config.js and extend the theme:

js
export default {
content: [
"./index.html",
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {
colors: {
'brand-blue': '#0066FF',
'brand-purple': '#7C3AED',
'brand-pink': '#EC4899',
},
},
},
plugins: [],
}

Now you can use bg-brand-blue, text-brand-purple, border-brand-pink, etc.

Adding Custom Fonts

First, import your font in index.css:

css
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;

Then add it to your config:

js
theme: {
extend: {
fontFamily: {
'sans': ['Inter', 'system-ui', 'sans-serif'],
},
},
}

Now font-sans uses Inter instead of the system default.

Creating Custom Utilities

Sometimes you need a style that's not in Tailwind. Add it to index.css:

css
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
.text-shadow {
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
}

The @layer utilities directive tells Tailwind to treat these as utilities, so they work with modifiers like hover: and md:.

Component Libraries to Speed Up Development

Once you're comfortable with Tailwind, check out these component libraries. They give you pre-built components that you can copy and customize:

  • Headless UI - Unstyled components by the Tailwind team. Great for dropdowns, modals, tabs.

  • Flowbite React - A UI component library that offers buttons, dropdowns, modals, datepickers, and more. You can plug them directly into your React app.

  • DaisyUI- Component classes built on top of Tailwind. Add semantic names like btn, card, navbar.

  • Shadcn UI - Copy-paste components. You own the code. Includes forms, charts, data tables.

These aren't installed packages that add bloat. They're just well-designed examples you copy into your project.

Production Optimization Tips

Before you deploy, here are a few tweaks to make your site faster:

Purge unused styles - Tailwind does this automatically based on your content config, but double-check your paths are correct.

  • Enable minification - Vite does this automatically in production builds. CRA does too.

  • Use PurgeCSS for extra cleanup- Only necessary if you have custom CSS mixed with Tailwind:

bash
npm install -D @fullhuman/postcss-purgecss
  • Compress your build - Most hosting platforms (Vercel, Netlify) do this automatically. Run a production build and check the size:
bash
npm run build

Your CSS file should be under 10KB for most projects. If it's over 50KB, you might have misconfigured the content paths.

Wrapping Up

You now know how to set up Tailwind CSS with React using either Vite (recommended) or Create React App. You've built a real component and learned the most important utility classes. The key takeaway? Utility classes might feel weird at first, but they're faster than writing custom CSS once you get used to them. You'll never go back to traditional stylesheets.


Windframe is an AI visual editor for rapidly building stunning web UIs & websites

Start building stunning web UIs & websites!

Build from scratch or select prebuilt tailwind templates