Home / Blog / Master TailwindCSS 4 for Vue
Master TailwindCSS 4 for Vue

Master TailwindCSS 4 for Vue

Daniel Kelly
Daniel Kelly
Updated: February 27th 2025

Vue.js and TailwindCSS make a great team when it comes to creating beautiful scalable apps. Vue’s component-based approach makes it a great fit for use with Tailwind’s intuitive and plentiful utility classes.

The latest version of TailwindCSS (version 4) just released in January 2025. It brings even more powerful styling tools, a streamlined setup process, and more! Let’s see how to use it in a Vue 3 project.

Create A Vue Project

First let’s create a new Vue project from scratch to style with Tailwind.

 npm init vue@latest

You can choose whatever options you’d like, it doesn’t matter for this tutorial. If you’re interested, I chose these.

Vue scaffolding prompts and answers

Install Tailwind CSS 4 with Vite

Next we’ll install TailwindCSS with it’s first party Vite plugin.

  1. Use npm to install:
npm install tailwindcss @tailwindcss/vite
  1. Then register the plugin with Vite.
// vite.config.ts|js

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
import tailwindcss from "@tailwindcss/vite";

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    vueDevTools(),
    tailwindcss(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    },
  },
})
  1. Finally import tailwindcss into src/assets/main.css
/* /src/assets/main.css */
@import "tailwindcss";
  1. Congrats! You can now start using tailwind in your Vue.js components to style your app to your hearts content! No need to declare your content files in a tailwind config like in v3!
<!--App.vue-->
<template>
  <h1 class="bg-blue-500 text-white p-5">Hello Tailwind CSS!</h1>
</template>

Configure Tailwind CSS for a Vue.js Project

If the default tailwind theme is enough for you, then there’s no need to do anything else but you might want to configure it for your project’s unique needs. No problem, head on over to tailwind.config.ts … wait… no… that’s not right. In Tailwind v4 you can configure your theme styles in a .css file! What a novel idea! Configuring styles in a .cssfile instead of a .js file 🤪

/* /src/assets/main.css */
@import "tailwindcss";
@theme {
  /* extend the default theme with custom variables */
  --color-primary: oklch(0.53 0.12 118.34);
  /* or override the default theme */
  --breakpoint-sm: 30rem;
}

These configs are called “theme variables” in the TailwindCSS docs. They are used to generate utility classes but also compile to regular ol’ CSS custom properties (variables) of the same name so you can use them in HTML via inline styles…

<div style="background-color: var(--color-primary)">
  <!-- ... -->
</div>

or in CSS files…

p {
    background-color: var(--color-primary);
}

or via JavaScript…

window.getComputedStyle(document.body).getPropertyValue('--color-primary')

They aren’t quite the same thing as CSS variables defined in :root as they’re also used for utility class generation, thus they are defined under a Tailwind specific @theme directive. You can learn more about how these theme variables map to their generated class names in the TailwindCSS docs.

Use Tailwind Container Queries in a Vue Project

One really big win in Tailwind CSS version 4 is built in support for container queries. Take this simple PostCard component for example.

<!--PostCard.vue-->
<template>
<article class="@container bg-white rounded-lg shadow-sm">
    <!-- Card content adapts based on container width -->
    <!-- flex makes image and title side by side at larger sizes 
    (and stacked at smaller sizes) -->
    <div class="@md:flex @md:items-center p-4 gap-4">
        <img :src="post.image" class="@md:w-1/3 w-full rounded-lg object-cover" />
        <span>{{ post.title }}</span>
    </div>
</article>
</template>

<script setup lang="ts">
defineProps<{
  post: {
    title: string
    image: string
  }
}>()
</script>

On larger screens it will display the image and title side by side but then on smaller screens they will stack.

PostCard displayed with image and title text displayed side by side with flex

PostCard displayed with image and title text stacked on mobile

BUT it’s not just screen size it accounts for. The containing element’s size is also taken into account. Meaning that if we use the component within another element that has a restricted width, we’ll get the stacked version of the card even if the site is being viewed at full desktop size.

<div class="w-96">
    <ProductCard />
</div>
Post card stacked when used within a div with constrained width via Tailwind’s w-96 class

Use TailwindCSS for 3d Transformations in a Vue.js Project

TailwindCSS version 4 also comes with new utility classes for applying CSS transforms in a 3d space. Checkout this cool example of a transformed blog post card from the version launch announcement.

Post card transformed in 3d space so that it appears to be laying down on a 3d surface at an angle

The above could be accomplished in a similar fashion in Vue with code that looks something like this.

<div class="perspective-distant">
  <PostCard class="rotate-x-51 rotate-z-43 transform-3d"/>
</div>

Use TailwindCSS to Create Awesome Gradients in Your Vue Projects

In TailwindCSS version 4 there are plenty more options for creating different gradient variants including radial, conic, and linear gradients (with custom angles).

conic, radial, and linear gradients showcased in use on circle elements created with divs and TailwindCSS utility classes

conic, radial, and linear gradients showcased in use on circle elements created with divs and TailwindCSS utility classes

<div class="flex items-center gap-4 mt-10 ml-10">
    <div class="size-24 rounded-full bg-conic/[in_hsl_longer_hue] from-red-600 to-red-600"></div>
    <div class="size-24 rounded-full bg-radial-[at_25%_25%] from-white to-zinc-900 to-75%"></div>
    <div class="size-24 rounded-full bg-linear-45 from-indigo-500 via-purple-500 to-pink-500"></div>
    <div class="size-24 rounded-full bg-linear-0 from-indigo-500 via-red-500 to-orange-500"></div>
  </div>

Use Tailwind CSS Appear Transitions for Entering Transitions on Page Load in Vue.js

The Vue.js Transition component has an appear prop that’s useful for animating elements onto the page when it first loads. With TailwindCSS version 4, we can omit JavaScript from the picture altogether with the starting variant.

appear.gif

<div class="starting:opacity-0 transition-all duration-1000 size-24 rounded-full bg-red-800"></div>

This accomplished with the @starting-style feature of CSS. Do note that this is NOT supported on all browsers yet but as a progressive enhancement it would work great!

Autoresize Textareas in Vue with TailwindCSS Version 4

In times past it was common to use JavaScript to resize a textarea to fit it’s content. No more! Now it’s possible with the TailwindCSS field-sizing-content class alone.

text-area-resize.gif

<textarea class="field-sizing-content border-gray-500 border w-full rounded p-3"></textarea>

Use the Not Variant with TailwindCSS on a Vue Router Link for Simpler Styling Without Overrides

TailwindCSS version 4 added the a new not-* variant which adds support for the CSS :not() pseudo-class. This means we can style elements with less on overrides which is useful for avoiding specificity issues, typing out less classes, and enjoying an easier to follow mental model.

In the below example we are able to easily handle the various states of a RouterLink with a combination of variants combined with not- .

<RouterLink
    to="/"
    class="
      transition-colors 
      duration-200
      not-hover:text-white 
      not-active:text-white 
      hover:text-blue-500 
      active:text-blue-700
      not-hover:bg-blue-500 
      not-active:bg-blue-500 
      hover:bg-blue-100 
      active:bg-blue-200
    "
  >
    Home
  </RouterLink>
not-tailwind.gif

As an added bonus, it also supports negating media queries and supports rules.

<div class="not-supports-hanging-punctuation:px-4">
  <!-- ... -->
</div>

Use Tailwind Version 4 in Your Vue.js Apps Now!

Tailwind version 4 is officially stable and ready to use in your Vue applications and it obviously comes with some really nice enhancements. In this article we’ve reviewed some of the ones I find most interesting but checkout the full release announcement for even more details.

Ready to get started? Just install Tailwind as discussed above or checkout the Nuxt UI v3 (alpha) library, it’s already compatible and it can be installed in a regular Vue or Nuxt project.

Related Courses

Start learning Vue.js for free

Daniel Kelly
Daniel Kelly
Daniel is the lead instructor at Vue School and enjoys helping other developers reach their full potential. He has 10+ years of developer experience using technologies including Vue.js, Nuxt.js, and Laravel.

Comments

Latest Vue School Articles

Master JavaScript Error Handling

Master JavaScript Error Handling

Master JavaScript error handling with try-catch, common error types, custom error classes, and async handling. Learn best practices in our latest course
Daniel Kelly
Daniel Kelly
Running DeepSeek AI Locally and Chatting from VS Code

Running DeepSeek AI Locally and Chatting from VS Code

Running DeepSeek AI Locally and Chatting from VS Code Tutorials - Vue School Articles
Daniel Kelly
Daniel Kelly

Our goal is to be the number one source of Vue.js knowledge for all skill levels. We offer the knowledge of our industry leaders through awesome video courses for a ridiculously low price.

More than 200.000 users have already joined us. You are welcome too!

Follow us on Social

© All rights reserved. Made with ❤️ by BitterBrains, Inc.