Table of Contents
- Prerequisites
- Setting Up a Vue.js Project
- Installing Tailwind CSS
- Configuring Tailwind CSS for Vue.js
- Using Tailwind CSS in Vue Components
- Advanced Tailwind + Vue.js Techniques
- Troubleshooting Common Issues
- Conclusion
- References
Prerequisites
Before getting started, ensure you have the following installed:
- Node.js (v14.0.0 or later) and npm/yarn (npm is included with Node.js).
- Basic familiarity with Vue.js (components, directives, and project structure).
- Basic understanding of CSS (selectors, classes, responsive design).
Setting Up a Vue.js Project
We’ll cover two popular ways to set up a Vue project: Vite (Vue’s official build tool, fast and lightweight) and Vue CLI (older but still widely used).
Option 1: Using Vite (Recommended)
Vite is the preferred tool for new Vue projects due to its fast hot module replacement (HMR) and optimized build process.
-
Create a new Vue project with Vite:
npm create vite@latest my-vue-tailwind-app -
Follow the prompts:
- Select Vue as the framework.
- Choose a variant (JavaScript or TypeScript; we’ll use JavaScript for simplicity).
-
Navigate to the project directory and install dependencies:
cd my-vue-tailwind-app npm install -
Start the development server to verify the setup:
npm run devYou should see a default Vue app running at
http://localhost:5173.
Option 2: Using Vue CLI
If you prefer Vue CLI (e.g., for legacy projects), follow these steps:
-
Install Vue CLI globally (if not already installed):
npm install -g @vue/cli -
Create a new project:
vue create my-vue-tailwind-app -
Select a preset (e.g., “Default (Vue 3)” or “Manually select features” for customization).
-
Navigate to the project and start the dev server:
cd my-vue-tailwind-app npm run serve
Installing Tailwind CSS
Once your Vue project is set up, install Tailwind CSS and its dependencies. Tailwind requires postcss and autoprefixer for processing CSS.
-
In your project directory, install Tailwind via npm:
npm install -D tailwindcss postcss autoprefixer -
Generate Tailwind’s configuration files (
tailwind.config.jsandpostcss.config.js):npx tailwindcss init -p
This creates two files in your project root:
tailwind.config.js: Configures Tailwind’s theme, plugins, and content paths.postcss.config.js: Tells PostCSS to use Tailwind and Autoprefixer.
Configuring Tailwind CSS for Vue.js
To ensure Tailwind processes your Vue components and generates the correct CSS, update the tailwind.config.js file.
-
Open
tailwind.config.jsand modify thecontentarray to include paths to your Vue components and templates:/** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}", // Scan all Vue/JS/TS files in src/ ], theme: { extend: {}, }, plugins: [], }The
contentarray tells Tailwind which files to scan for class names (to avoid including unused CSS in production). -
Add Tailwind’s directives to your main CSS file. Create or modify
src/assets/main.css(orsrc/index.cssin some setups) and add:@tailwind base; @tailwind components; @tailwind utilities; -
Import this CSS file into your root Vue component (usually
src/main.js):import { createApp } from 'vue' import App from './App.vue' import './assets/main.css' // Import Tailwind styles createApp(App).mount('#app')
Using Tailwind CSS in Vue Components
Now that Tailwind is configured, let’s use it in Vue components.
Basic Class Usage
Tailwind’s utility classes can be applied directly to HTML elements in Vue templates, just like regular CSS classes.
Example: A simple button component (src/components/HelloWorld.vue):
<template>
<button class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded transition duration-300">
Click Me
</button>
</template>
Here, classes like bg-blue-500 (background color), hover:bg-blue-600 (hover state), and rounded (rounded corners) style the button.
Conditional Classes with Vue Directives
Vue’s v-bind:class (or :class shorthand) lets you dynamically apply Tailwind classes based on component state.
Example 1: Object Syntax (Conditional Classes)
Apply classes conditionally using an object where keys are class names and values are booleans:
<template>
<div>
<button
:class="{
'bg-green-500 hover:bg-green-600': isActive,
'bg-gray-500 cursor-not-allowed': !isActive
}"
class="text-white font-bold py-2 px-4 rounded"
@click="isActive = !isActive"
>
{{ isActive ? 'Active' : 'Inactive' }}
</button>
</div>
</template>
<script>
export default {
data() {
return {
isActive: false
};
}
};
</script>
Example 2: Array Syntax (Combining Classes)
Use an array to apply multiple classes conditionally:
<template>
<div :class="[isError ? 'text-red-500' : 'text-green-500', 'font-medium']">
Status: {{ isError ? 'Error' : 'Success' }}
</div>
</template>
<script>
export default {
data() {
return {
isError: true
};
}
};
</script>
Extracting Classes with @apply
For repeated utility patterns (e.g., a custom button style used across components), use Tailwind’s @apply directive to extract classes into a CSS class.
Example: Create a reusable button style in src/assets/main.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Custom component class */
.btn-primary {
@apply bg-indigo-600 hover:bg-indigo-700 text-white font-semibold py-2 px-6 rounded-lg shadow-md transition-all duration-200;
}
Now use btn-primary in your Vue component:
<template>
<button class="btn-primary">Reusable Button</button>
</template>
Advanced Tailwind + Vue.js Techniques
Customizing Tailwind’s Theme
Tailwind’s default theme (colors, fonts, spacing, etc.) can be extended or overridden in tailwind.config.js.
Example: Add Custom Colors and Fonts
Update tailwind.config.js to extend the theme:
module.exports = {
content: ["./index.html", "./src/**/*.{vue,js,ts}"],
theme: {
extend: {
colors: {
brand: {
primary: '#2563eb', // Custom primary color
secondary: '#4f46e5', // Custom secondary color
},
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'], // Custom font
},
},
},
plugins: [],
}
Now use these custom values in components:
<template>
<h1 class="font-sans text-brand-primary">Hello, Custom Theme!</h1>
</template>
Responsive Design with Tailwind
Tailwind includes built-in responsive breakpoints (e.g., sm, md, lg) to adapt layouts for different screen sizes. Prefix classes with breakpoints to apply styles conditionally.
Example: A responsive card component:
<template>
<div class="bg-white rounded-lg shadow p-4 sm:p-6 md:p-8">
<h2 class="text-lg sm:text-xl md:text-2xl font-bold">Responsive Card</h2>
<p class="text-gray-600 mt-2">Adapts to screen size!</p>
</div>
</template>
Breakpoints (default):
sm: 640px+md: 768px+lg: 1024px+xl: 1280px+2xl: 1536px+
Dark Mode Integration
Tailwind supports dark mode via the dark: prefix. Enable it by updating tailwind.config.js:
-
Set
darkMode: 'class'intailwind.config.js(class-based dark mode):module.exports = { darkMode: 'class', // Enable class-based dark mode content: ["./index.html", "./src/**/*.{vue,js,ts}"], // ... rest of config } -
Add a toggle to switch between light/dark modes in your Vue app. Example using a button:
<template> <button @click="toggleDarkMode" class="p-2 rounded-full bg-gray-200 dark:bg-gray-700"> {{ isDarkMode ? 'Light Mode' : 'Dark Mode' }} </button> </template> <script> export default { data() { return { isDarkMode: false, }; }, methods: { toggleDarkMode() { this.isDarkMode = !this.isDarkMode; document.documentElement.classList.toggle('dark', this.isDarkMode); }, }, mounted() { // Check for saved dark mode preference or system preference if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) { document.documentElement.classList.add('dark'); this.isDarkMode = true; } }, }; </script> -
Use
dark:prefixes to style dark mode:<template> <div class="bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 min-h-screen"> <!-- Content --> </div> </template>
Using Tailwind with Vue 3’s <script setup>
Vue 3’s <script setup> syntax simplifies component logic. Tailwind works seamlessly with it—here’s an example with reactive class binding:
<template>
<button
:class="buttonClasses"
@click="isActive = !isActive"
>
{{ isActive ? 'Active' : 'Inactive' }}
</button>
</template>
<script setup>
import { ref, computed } from 'vue';
const isActive = ref(false);
// Compute classes reactively
const buttonClasses = computed(() => ({
'bg-purple-500 hover:bg-purple-600': isActive.value,
'bg-gray-300 hover:bg-gray-400 cursor-not-allowed': !isActive.value,
'text-white font-bold py-2 px-4 rounded transition': true, // Always applied
}));
</script>
Troubleshooting Common Issues
Classes Not Applying?
- Check
tailwind.config.js: Ensure thecontentarray includes paths to your Vue files (e.g.,./src/**/*.vue). - Restart the Dev Server: Sometimes Vite/Vue CLI needs a restart to pick up config changes.
- Verify CSS Import: Ensure
main.css(with@tailwinddirectives) is imported inmain.js.
Build Errors (e.g., PostCSS Issues)
- Missing Dependencies: Reinstall
tailwindcss,postcss, andautoprefixer:npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
Unused CSS in Production
Tailwind automatically purges unused classes in production (via its JIT compiler), but if you’re seeing extra CSS:
- Ensure
NODE_ENV=productionwhen building:npm run build
Conclusion
Combining Vue.js and Tailwind CSS streamlines UI development by leveraging Vue’s component-based architecture and Tailwind’s utility-first styling. With this setup, you can build responsive, customizable, and maintainable apps faster than ever.
Experiment with custom themes, responsive designs, and dark mode to take your Vue + Tailwind projects to the next level!