See all posts

How to Install Tailwind CSS in Vue.js

How to Install Tailwind CSS in Vue.js

Tailwind Vue

You're building a Vue app and tired of writing the same CSS over and over. Someone mentioned Tailwind CSS, but you're not sure how to get started or if it's worth the setup time. I'm going to show you exactly how to install Tailwind CSS in Vue.js (both Vue 3 with Vite and the older Vue CLI method). You'll build a real component, learn the gotchas that trip up most developers, and understand why this combo is so powerful.

Table of Content

Why Tailwind and Vue.js Work So Well Together

Let me tell you why this combination clicked for me. Vue's component system and Tailwind's utility classes complement each other perfectly.

No more context switching: You write your HTML, logic, and styles all in one .vue file. No jumping between files or trying to remember which class you defined in which stylesheet.

Scoped by default: Vue's components are naturally isolated. Add Tailwind's utilities, and you don't worry about class name conflicts or CSS specificity battles.

Faster prototyping: Need to move that button 10 pixels to the right? Just change ml-2 to ml-4. No hunting through CSS files or creating new classes.

Smaller bundle sizes: Tailwind's purge feature (now called content scanning) removes unused styles automatically. Your final CSS file is tiny, even though Tailwind has thousands of utility classes available.

Here's what makes this stack different from Bootstrap or Vuetify: you're not fighting against opinionated component styles. You build exactly what your design calls for, using small building blocks.

Before You Start: Here's What You'll Need

Make sure you have these installed: Node.js (version 18 or newer) - Download from nodejs.org. Node 18 reaches end-of-life in April 2025, so I recommend grabbing Node 20 LTS or newer.

Check your version:

bash
node --version

If it's 18 or higher, you're good.

npm or yarn - Comes with Node.js automatically. Either works fine.

Basic Vue knowledge - You should understand components, props, and the template syntax. If not, spend 30 minutes on Vue's official tutorial first.

A code editor - I use VS Code with the Volar extension for Vue 3. Makes life easier. That's all you need. Let's build this thing.

Method 1: Vue 3 + Vite + Tailwind (The Modern Way)

This is the setup I use for every new project. It's fast, clean, and officially recommended by both the Vue and Tailwind teams.

Step 1: Create Your Vue 3 Project

Open your terminal and run:

bash
npm create vue@latest my-vue-app

You'll see several prompts. Here's what I typically choose:

  • TypeScript? No (unless you know you need it)
  • JSX Support? No
  • Vue Router? Yes (if building a multi-page app)
  • Pinia? Yes (if you need state management)
  • Vitest? Your choice
  • ESLint? Yes
  • Prettier? Yes

Navigate into your project:

bash
cd my-vue-app
npm install

This creates a Vue 3 project using Vite. Unlike the old Vue CLI, Vite starts your dev server in under a second. You'll notice the difference immediately.

Step 2: Install Tailwind CSS

Now add Tailwind and its dependencies:

bash
npm install -D tailwindcss@latest postcss autoprefixer

Initialize Tailwind:

bash
npx tailwindcss init -p

This creates two files:

  • tailwind.config.js - Where you customize Tailwind
  • postcss.config.js - Configures PostCSS to process your CSS

Pro tip: If you're using Tailwind v4 (the newest version), the setup is even simpler. Instead of the above, you'd run:

bash
npm install -D @tailwindcss/vite

Then register the Vite plugin (I'll show you how in a moment). For now, I'll stick with the v3 approach since it's what most people use.

Step 3: Configure Tailwind for Vue Files

Open tailwind.config.js and replace everything with this:

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

The content array tells Tailwind where to look for class names. It scans these files and only generates CSS for the classes you actually use. This keeps your final bundle small.

Notice the pattern ./src/**/*.{vue,js,ts,jsx,tsx}:

  • ** means "any folder, any depth"
  • {vue,js,ts,jsx,tsx} means "files ending in any of these extensions"

If you add files outside src/, update this array.

Step 4: Import Tailwind Styles

Open src/assets/main.css (or create it if it doesn't exist). Delete everything and add:

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

These three lines import:

  • base - Resets and fundamental styles
  • components - Component-level styles (rarely used, but available)
  • utilities - All the utility classes like flex, bg-blue-500, text-xl

Now make sure this file is imported in your app. Open src/main.js and check for this line near the top:

js
import './assets/main.css'

If it's missing, add it. This imports your Tailwind styles into the entire app.

Step 5: Test That Everything Works

Let's verify Tailwind is running. Open src/App.vue and replace its content with:

vue
<template>
<div class="flex items-center justify-center min-h-screen bg-linear-to-br from-blue-500 to-purple-600">
<div class="bg-white rounded-2xl shadow-2xl p-8 max-w-md">
<h1 class="text-4xl font-bold text-gray-900 mb-4">
🎉 Success!
</h1>
<p class="text-gray-600 text-lg">
Tailwind CSS is working perfectly in your Vue 3 project.
</p>
</div>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>

Start your dev server:

bash
npm run dev

Open your browser to the URL shown (usually http://localhost:5173). You should see a centered white card with a gradient background.

Preview

🎉 Success!

Tailwind CSS is working perfectly in your Vue 3 project.

If you see styled content, congratulations! Tailwind is running.

Method 2: Vue CLI + Tailwind (Legacy Approach)

The Vue CLI is older and slower than Vite, but some teams still use it. If you're maintaining an existing Vue CLI project, here's how to add Tailwind.

Important: The Vue team now recommends using create-vue (which uses Vite) instead of Vue CLI. But if you must use Vue CLI, here's the process.

Step 1: Create a Vue CLI Project If you don't have Vue CLI installed:

bash
npm install -g @vue/cli

Create your project:

bash
vue create my-vue-app

Choose your preset (default works fine) and wait. This takes 2-3 minutes, which is why Vite is better.

Navigate into the folder:

bash
cd my-vue-app

Step 2: Install Tailwind

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

Same as before.

Step 3: Configure Tailwind

Open tailwind.config.js:

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

Notice we include ./public/**/*.html for Vue CLI projects.

Step 4: Add Tailwind Directives

Create or open src/assets/tailwind.css and add:

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

Import this in src/main.js:

js
import './assets/tailwind.css'

Step 5: Test It

Replace src/App.vue with:

vue
<template>
<div class="flex items-center justify-center min-h-screen bg-blue-500">
<h1 class="text-4xl font-bold text-white">
Tailwind + Vue CLI Works!
</h1>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>

Run:

bash
npm run serve

Open http://localhost:8080. You should see white text on a blue background.

Building Your First Real Component

Let's build something useful: a profile card component. This shows off Tailwind's strengths with real-world styling.

Create src/components/ProfileCard.vue:

vue
<template>
<div class="max-w-sm mx-auto bg-white rounded-2xl shadow-lg overflow-hidden hover:shadow-2xl transition-shadow duration-300">
<!-- Header with gradient -->
<div class="h-32 bg-linear-to-r from-indigo-500 via-purple-500 to-pink-500"></div>
<!-- Profile Image -->
<div class="relative px-6 -mt-16">
<img
:src="avatar"
:alt="name"
class="w-32 h-32 rounded-full border-4 border-white shadow-xl"
/>
</div>
<!-- Content -->
<div class="px-6 py-4">
<h2 class="text-2xl font-bold text-gray-900 mb-1">
{{ name }}
</h2>
<p class="text-gray-600 mb-4">
{{ title }}
</p>
<!-- Stats Grid -->
<div class="grid grid-cols-3 gap-4 mb-6">
<div class="text-center">
<p class="text-2xl font-bold text-indigo-600">{{ followers }}</p>
<p class="text-xs text-gray-500">Followers</p>
</div>
<div class="text-center">
<p class="text-2xl font-bold text-purple-600">{{ following }}</p>
<p class="text-xs text-gray-500">Following</p>
</div>
<div class="text-center">
<p class="text-2xl font-bold text-pink-600">{{ posts }}</p>
<p class="text-xs text-gray-500">Posts</p>
</div>
</div>
<!-- Action Buttons -->
<div class="flex gap-3">
<button class="flex-1 bg-indigo-600 text-white py-2 rounded-lg hover:bg-indigo-700 transition-colors font-semibold">
Follow
</button>
<button class="flex-1 border-2 border-indigo-600 text-indigo-600 py-2 rounded-lg hover:bg-indigo-50 transition-colors font-semibold">
Message
</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ProfileCard',
props: {
name: {
type: String,
default: 'Sarah Johnson'
},
title: {
type: String,
default: 'Product Designer'
},
avatar: {
type: String,
default: 'https://i.pravatar.cc/150?img=47'
},
followers: {
type: Number,
default: 2847
},
following: {
type: Number,
default: 314
},
posts: {
type: Number,
default: 126
}
}
}
</script>

Now use it in src/App.vue:

vue
<template>
<div class="min-h-screen bg-gray-100 flex items-center justify-center p-4">
<ProfileCard />
</div>
</template>
<script>
import ProfileCard from './components/ProfileCard.vue'
export default {
name: 'App',
components: {
ProfileCard
}
}
</script>

Run your dev server and check the result. You've got a professional-looking profile card with:

  • Gradient header
  • Circular avatar with shadow
  • Stats grid
  • Interactive buttons with hover effects

All without writing a single line of custom CSS. That's the power of Tailwind.

Understanding the Tailwind Classes You Just Used

Let me break down some key patterns:

Responsive Grid

vue
<div class="grid grid-cols-3 gap-4">

Creates a 3-column grid with gap spacing. On mobile, you could change this to grid-cols-1 sm:grid-cols-3 to stack vertically on small screens.

Hover States

vue
class="hover:shadow-2xl hover:bg-indigo-700"

Applies styles only on hover. Tailwind automatically adds the :hover pseudo-class. Works with focus, active, and other states too.

Transitions

vue
class="transition-colors duration-300"

Smoothly animates color changes over 300ms. You can animate shadows, transforms, opacity - anything CSS can transition.

Negative Margins

vue
class="-mt-16"

Pulls the avatar up over the header. Negative values work with margin and translate utilities.

Flexbox Utilities

js
class="flex gap-3"

Makes a flex container with spacing between children. Much cleaner than margin hacks. Learn more about these patterns in the official Tailwind documentation.

Customizing Tailwind for Your Project

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

Adding Brand Colors

Open tailwind.config.js:

js
export default {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
'brand': {
50: '#f0f9ff',
100: '#e0f2fe',
500: '#0ea5e9',
600: '#0284c7',
900: '#0c4a6e',
},
},
},
},
plugins: [],
}

Now use bg-brand-500, text-brand-600, etc. in your components.

Custom Fonts

Import your font in main.css:

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

Add it to your config:

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

Now font-sans uses Inter globally.

Creating Reusable Component Classes

Sometimes you need a style you'll use in multiple places. Add it to main.css:

css
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn-primary {
@apply bg-indigo-600 text-white px-6 py-2 rounded-lg font-semibold hover:bg-indigo-700 transition-colors;
}
.card {
@apply bg-white rounded-xl shadow-lg p-6;
}
}

Now use <button class="btn-primary"> instead of writing all those utilities every time.

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

Using Tailwind with Vue's Composition API

If you're using Vue 3's Composition API, Tailwind works the same way. Here's a quick example:

vue
<template>
<div class="p-4">
<button
@click="count++"
:class="buttonClass"
>
Clicked {{ count }} times
</button>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const count = ref(0)
const buttonClass = computed(() => {
return count.value > 5
? 'bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition-colors'
: 'bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg transition-colors'
})
</script>

You can dynamically generate class strings based on reactive data. This is where Vue's reactivity and Tailwind's utilities really shine together.

Tailwind with Vue Router

When using Vue Router, you might want active link styles. Here's a clean approach:

vue
<template>
<nav class="bg-white shadow">
<div class="max-w-7xl mx-auto px-4">
<div class="flex space-x-8">
<router-link
to="/"
class="py-4 border-b-2 transition-colors"
active-class="border-indigo-500 text-indigo-600"
exact-active-class="border-indigo-500 text-indigo-600"
>
Home
</router-link>
<router-link
to="/about"
class="py-4 border-b-2 border-transparent text-gray-600 hover:text-gray-900 hover:border-gray-300 transition-colors"
active-class="border-indigo-500 text-indigo-600"
>
About
</router-link>
</div>
</div>
</nav>
</template>

The active-class prop applies Tailwind utilities to active links automatically.

Common Problems & Solutions

"Tailwind classes aren't working" Symptom: You write bg-blue-500 but nothing happens.

Solutions:

  1. Check that main.css is imported in main.js

  2. Verify the content paths in tailwind.config.js include all your Vue files

  3. Restart your dev server (sometimes it needs a kick)

  4. Clear your browser cache (Ctrl+Shift+R or Cmd+Shift+R)

"Cannot find module 'tailwindcss'"

Symptom: Error during build or dev server won't start. Solution: Reinstall dependencies:

bash
rm -rf node_modules package-lock.json
npm install
npm install -D tailwindcss postcss autoprefixer

"Some classes work, others don't"

Symptom: Basic classes like flex work, but bg-brand-500 doesn't.

Solution: You forgot to restart the dev server after changing tailwind.config.js. Custom configurations require a restart.

Styles disappear in production Symptom: Everything looks great in development, but your production build has no styles.

Solution: Your content paths don't match your actual file locations. Double-check tailwind.config.js:

js
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}", // Make sure this matches your structure
]

If your components are in a different folder, add that path.

Vite port already in use Symptom: "Port 5173 is already in use"

Solution: Either close the other Vite process or use a different port:

bash
npm run dev -- --port 3000

Component Libraries That Work with Vue + Tailwind

Don't want to build every component from scratch? These libraries offer pre-built Vue components styled with Tailwind:

Headless UI - Unstyled, accessible components by the Tailwind team. Great for dropdowns, modals, tabs. You add your own Tailwind styles.

Flowbite Vue - Pre-styled components ready to use. Includes buttons, cards, navbars, forms, and more.

DaisyUI - Adds semantic component classes on top of Tailwind. Write <button class="btn"> instead of a long list of utilities.

Radix Vue - Unstyled, accessible components with great keyboard navigation. Similar philosophy to Headless UI.

These aren't dependencies that bloat your bundle. They're either unstyled primitives (you add Tailwind classes) or carefully-designed component collections that use Tailwind under the hood.

Wrapping Up

You now know how to set up Tailwind CSS with Vue.js using either Vite (recommended) or Vue CLI. You've built real components and learned how to customize everything. The combination of Vue's reactivity and Tailwind's utilities is incredibly productive once you get used to it. You'll prototype faster, maintain cleaner code, and ship smaller CSS bundles.


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