See all posts

How to Install Tailwind CSS in Vue.js

How to Install Tailwind CSS in Vue.js

Using Tailwind CSS with Vue.js

If you’re building a Vue application, chances are you’ve already felt the friction of managing CSS as your project grows. Reusable components help, but traditional stylesheets still tend to sprawl, duplicate, and slowly become harder to reason about.

Tailwind CSS takes a different approach. Instead of writing custom CSS for every layout and component, you build designs using small, composable utility classes directly in your templates. When paired with Vue’s component model, this workflow feels surprisingly natural.

This guide walks through setting up Tailwind CSS with Vue.js using both modern and legacy tooling. You’ll build real components, learn where people usually get stuck, and see how this stack holds up in real projects.

Table of Content

Why Tailwind Works So Well with Vue

Vue components already encourage you to think in small, reusable pieces. Tailwind fits neatly into that mindset.

Everything lives in one place Templates, logic, and styling sit together in a single .vue file. You don’t need to jump between files or remember where a class was defined.

No style collisions Vue components are isolated by design. Combined with Tailwind’s utilities, you avoid most of the specificity and naming problems that show up in larger CSS codebases.

Fast iteration Tweaking spacing, colors, or layout is immediate. Changing ml-2 to ml-4 is faster than editing a stylesheet, recompiling, and checking side effects.

Lean production builds Tailwind scans your Vue files and only includes the utilities you actually use. Even though Tailwind ships with thousands of classes, the final CSS output stays small.

Unlike component libraries that impose visual decisions, Tailwind gives you primitives. You build exactly what your design needs, without fighting default styles.

Prerequisite

Make sure you have the following in place:

  • Node.js 18 or newer Node 20 LTS or later is recommended for new projects.
bash
node --version
  • npm or yarn: Both work fine.

  • Basic Vue knowledge: You should be comfortable with components, props, and template syntax.

  • A code editor: VS Code with the Volar extension works well for Vue 3 projects.

That’s all you need to get started.

This is the setup most teams should use today. It’s fast, simple, and officially supported by both Vue and Tailwind.

Step 1: Create a Vue 3 Project

bash
npm create vue@latest my-vue-app
cd my-vue-app
npm install

Vite-based projects start almost instantly, which makes development feel much snappier than older tooling.

Step 2: Install Tailwind CSS

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

This creates:

  • tailwind.config.js for customization

  • postcss.config.js for CSS processing

Step 3: Configure Tailwind

Update tailwind.config.js:

js
export default {
content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};

The content option tells Tailwind where to look for class names. If Tailwind doesn’t see a class here, it won’t include it in the final build.

Step 4: Add Tailwind Directives

In src/assets/main.css:

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

Then import the file in src/main.js:

js
import "./assets/main.css";

Step 5: Confirm Everything Works

Replace App.vue with:

js
<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-xl p-8 max-w-md">
<h1 class="text-3xl font-bold mb-3">Setup Complete</h1>
<p class="text-gray-600">
Tailwind CSS is now working in your Vue project.
</p>
</div>
</div>
</template>

Run the dev server:

bash
npm run dev

Preview

Setup Complete

Tailwind CSS is now working in your Vue project.

If you see styled content, Tailwind is set up correctly.

Method 2: Vue CLI + Tailwind (Legacy Projects)

Vue CLI is no longer recommended for new projects, but many existing apps still use it.

Step 1: Create or Open a Vue CLI Project

bash
npm install -g @vue/cli
vue create my-vue-app
cd my-vue-app

Step 2: Install Tailwind

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

Step 3: Configure Content Paths

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

Step 4: Import Tailwind

Create src/assets/tailwind.css:

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

Import it in main.js:

js
import "./assets/tailwind.css";

Run the app with:

bash
npm run serve

Building a Real Component

Here’s a simple profile card that shows how Tailwind shines in component-based UIs.

You get layout, spacing, typography, hover states, and transitions without writing custom CSS. Everything stays readable and local to the component.

This approach scales well as components grow more complex.

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>
import ProfileCard from './components/ProfileCard.vue'
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: 22397,
},
following: {
type: Number,
default: 500,
},
posts: {
type: Number,
default: 126,
},
},
};
</script>

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

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>

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

name

Sarah Johnson

Product Designer

followers

22k

following

500

posts

126

Customizing Tailwind

Brand Colors

js
extend: {
colors: {
brand: {
500: '#0ea5e9',
600: '#0284c7',
},
},
}

Use them like:

js
<button class="bg-brand-500 text-white">Save</button>

Fonts

Import your font in CSS, then register it in tailwind.config.js. From there, utilities like font-sans apply it consistently across your app.

Conditional Styling with Vue Reactivity

Vue’s reactivity pairs well with Tailwind when styles depend on state.

vue
<template>
<button
:class="[
'px-4 py-2 rounded-md font-medium transition',
isActive ? 'bg-green-600 text-white' : 'bg-gray-200 text-gray-700',
]"
@click="isActive = !isActive"
>
Toggle
</button>
</template>
<script setup>
import { ref } from "vue";
const isActive = ref(false);
</script>

This keeps visual state logic close to application logic, which is easier to reason about than switching between CSS and JavaScript.

Reusable Styles Without Losing Tailwind’s Benefits

For patterns you use often, Tailwind supports component classes via @layer.

css
@layer components {
.btn-primary {
@apply bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700 transition;
}
}

Now your Vue templates stay readable:

js
<button class="btn-primary">Save changes</button>

This strikes a good balance between utility classes and reuse.

Tailwind with Vue Router

Navigation states are easy to handle with Tailwind.

js
<router-link
to="/settings"
class="px-3 py-2 text-gray-600 hover:text-gray-900"
active-class="text-indigo-600 font-semibold"
>
Settings
</router-link>

You don’t need custom CSS for active states—Vue Router and Tailwind handle it cleanly.

Common Issues and Fixes

Classes not applying: Check content paths and restart the dev server

Custom styles missing: Tailwind config changes always require a restart

Production styles missing: Content paths don’t match actual file locations

Most issues come down to configuration or stale dev servers.

Component Libraries That Pair Well

Headless UI – Unstyled, accessible primitives

Flowbite Vue – Ready-made Tailwind components

DaisyUI – Semantic component classes

Radix Vue – Accessible building blocks

These save time without locking you into rigid designs.

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.

Tailwind CSS and Vue.js form a practical, efficient pairing. You get fast iteration, predictable styling, and smaller CSS bundles, all while keeping components easy to reason about.

Once the workflow clicks, it’s hard to go back to traditional CSS's heavy setups. For most Vue projects today, this combination is a solid default.


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