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 Makes Vue Development Faster
- What You Need First
- Method 1: Vue 3 + Vite + Tailwind (Recommended)
- Method 2: Vue CLI + Tailwind (Legacy)
- Build Your First Component
- Common Problems & Solutions
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:
node --versionIf 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:
npm create vue@latest my-vue-appYou'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:
cd my-vue-appnpm installThis 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:
npm install -D tailwindcss@latest postcss autoprefixerInitialize Tailwind:
npx tailwindcss init -pThis creates two files:
tailwind.config.js- Where you customize Tailwindpostcss.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:
npm install -D @tailwindcss/viteThen 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:
/** @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:
@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:
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:
<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:
npm run devOpen 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:
npm install -g @vue/cliCreate your project:
vue create my-vue-appChoose your preset (default works fine) and wait. This takes 2-3 minutes, which is why Vite is better.
Navigate into the folder:
cd my-vue-appStep 2: Install Tailwind
npm install -D tailwindcss postcss autoprefixernpx tailwindcss init -pSame as before.
Step 3: Configure Tailwind
Open tailwind.config.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:
@tailwind base;@tailwind components;@tailwind utilities;Import this in src/main.js:
import './assets/tailwind.css'Step 5: Test It
Replace src/App.vue with:
<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:
npm run serveOpen 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:
<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:
<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
<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
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
class="transition-colors duration-300"Smoothly animates color changes over 300ms. You can animate shadows, transforms, opacity - anything CSS can transition.
Negative Margins
class="-mt-16"Pulls the avatar up over the header. Negative values work with margin and translate utilities.
Flexbox Utilities
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:
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:
@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:
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:
@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:
<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:
<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:
-
Check that
main.cssis imported inmain.js -
Verify the content paths in
tailwind.config.jsinclude all your Vue files -
Restart your dev server (sometimes it needs a kick)
-
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:
rm -rf node_modules package-lock.jsonnpm installnpm 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:
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:
npm run dev -- --port 3000Component 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!
