javascriptroom guide

How to Use Vue.js with Tailwind CSS

Vue.js and Tailwind CSS are two powerful tools in modern web development: Vue.js excels at building interactive, component-based user interfaces, while Tailwind CSS offers a utility-first approach to styling, enabling rapid UI development with minimal custom CSS. Combining them allows developers to create responsive, maintainable, and visually consistent applications efficiently. In this guide, we’ll walk through everything you need to know to integrate Tailwind CSS with Vue.js, from project setup to advanced customization. Whether you’re using Vue 2 or Vue 3 (we’ll focus on Vue 3, the latest version), this tutorial will help you leverage the best of both tools.

Table of Contents

  1. Prerequisites
  2. Setting Up a Vue.js Project
  3. Installing Tailwind CSS
  4. Configuring Tailwind CSS for Vue.js
  5. Using Tailwind CSS in Vue Components
  6. Advanced Tailwind + Vue.js Techniques
  7. Troubleshooting Common Issues
  8. Conclusion
  9. 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).

Vite is the preferred tool for new Vue projects due to its fast hot module replacement (HMR) and optimized build process.

  1. Create a new Vue project with Vite:

    npm create vite@latest my-vue-tailwind-app  
  2. Follow the prompts:

    • Select Vue as the framework.
    • Choose a variant (JavaScript or TypeScript; we’ll use JavaScript for simplicity).
  3. Navigate to the project directory and install dependencies:

    cd my-vue-tailwind-app  
    npm install  
  4. Start the development server to verify the setup:

    npm run dev  

    You 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:

  1. Install Vue CLI globally (if not already installed):

    npm install -g @vue/cli  
  2. Create a new project:

    vue create my-vue-tailwind-app  
  3. Select a preset (e.g., “Default (Vue 3)” or “Manually select features” for customization).

  4. 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.

  1. In your project directory, install Tailwind via npm:

    npm install -D tailwindcss postcss autoprefixer  
  2. Generate Tailwind’s configuration files (tailwind.config.js and postcss.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.

  1. Open tailwind.config.js and modify the content array 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 content array tells Tailwind which files to scan for class names (to avoid including unused CSS in production).

  2. Add Tailwind’s directives to your main CSS file. Create or modify src/assets/main.css (or src/index.css in some setups) and add:

    @tailwind base;  
    @tailwind components;  
    @tailwind utilities;  
  3. 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:

  1. Set darkMode: 'class' in tailwind.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  
    }  
  2. 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>  
  3. 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 the content array 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 @tailwind directives) is imported in main.js.

Build Errors (e.g., PostCSS Issues)

  • Missing Dependencies: Reinstall tailwindcss, postcss, and autoprefixer:
    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=production when 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!

References