EnglishEspañol
A general overview of Vue3 and Tailwind CSS 3.4

A general overview of Vue3 and Tailwind CSS 3.4


by Martijn Simons, Pixel-Nexus | 09 May 2025

Over the years, numerous frameworks have emerged to streamline web development for front-end developers. Among the most prominent are React, Angular, Vue, Bootstrap, and Tailwind CSS. In this brief article, I will provide an overview of the capabilities and features that make Vue and Tailwind CSS stand out, highlighting their value to developers in building efficient, scalable, and visually appealing web applications.

The setup process for both frameworks will not be covered in this article; however, I encourage you to explore our available tutorial to get started. (How to setup Vue3 and Tailwind CSS | Pixel-Nexus)

Vue Logo

Vue3

In the following sections I will be going over the segments of Vue I find important to get started. Examples provided are based on personal experience and Vue documentation. When working within VS code it is recommended to get the following plugins:

  • Typescript

  • Vue - Official

  • Tailwind CSS IntelliSense

The main features of Vue include, firstly, its declarative rendering, which extends standard HTML and allows us to manipulate the DOM based on a JavaScript state managed by Vue’s framework. Secondly, reactivity is a system of observers that tracks specific data properties. Based on the JavaScript state of the properties, Vue automatically updates the DOM elements  dependent on them.

Vue API styles

Before going into detail about the core Vue features, I will briefly showcase the two available API styles to use Vue as a framework.

Options API

The Options API defines a component's logic using an object that organizes various options. This object typically includes a data section, which holds the component's reactive properties, a methods section for functions that manipulate the state and trigger updates, and a mounted section, which handles the lifecycle hooks when the component is mounted.

Here's an example of the Options API:

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

Composition API

The primary distinction with the Composition API is that the component logic is organized using API functions rather than the object-based structure of the Options API. Although the functionalities of the sections remain similar, their names are modified. In this approach, the properties returned in the data section become reactive state variables defined at the top of the script. The methods section is transformed into functions located beneath these reactive state variables, which mutate the state and trigger updates. The mounted section is replaced with an imported API function from Vue that also manages lifecycle hooks.

Here's an example of the Composition API`:

<script setup>
import { ref, onMounted } from 'vue'

// reactive state
const count = ref(0)

function increment() {
  count.value++
}

onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

Depending on the requirements and goals for your project/production, arguments for both API styles can be made, for further information regarding the API styles and their usage please head over to the [Vue API style documentation.](Composition API FAQ | Vue.js)

From this point onwards code examples provided will be using the Composition API style.

Reactivity and Computed properties

Reactive properties

A data property that is watched by Vue for changes, whenever the value of this property is changed Vue will update the DOM elements that depend on it.

<script setup>
import { ref } from 'vue'

const count = ref(0)

function increment() {
  count.value++
}
</script>

<template>
  <button @click="increment">
    {{ count }}
  </button>
</template>

As illustrated in the example above, reactive state variables are wrapped in the ref API object, signaling to Vue that they need to be tracked. To access their values in the script section, you use count.value, however, within the template, the .value attribute is not required, as the ref objects are automatically unwrapped.

Computed properties

Complex logic that includes reactive data can make templates bloated and hard to maintain, when encountering a need for this, often a computed property is the solution. It reduces clutter and repetition of functionality. These properties can be accessed in the same way a ref object can, with the .value attribute.

<script setup>
import { reactive, computed } from 'vue'

const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})

// a computed ref
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No'
})
</script>

By default computed properties only have a getter function, they are read-only, it is possible however to create a writable computed property. By providing both a getter and a setter function, the .value attributes can now be used to set a new value.

Components

A vue SFC(Single File component) is a *.vue special file format, it encapsulates a component in a single file. This way each component has its own logic, template, and styles, enabling simplification of applications and ensuring reusability.

Props

External properties can be passed to a component, but they require an explicit declaration to ensure that Vue recognizes them for tracking. A prop is a custom attribute that facilitates data transfer from a parent component to a child component. These properties are reactive and can consist of various data types, including strings, numbers, objects, and functions. This reactivity promotes reusability, as the DOM elements automatically update whenever a prop value changes.

Parent component(partial):

const post = {
  id: 1,
  title: 'My Journey with Vue'
}


Function setNewId() {
*/.../*
}

<BlogPost :id="post.id" :title="post.title" @clicked_btn="setNewId"/>

Child component:

<script setup lang=ts>
const props = defineProps<{
  id: Number;
  title: String;
}>();

const emit = defineEmits([
 'clicked_btn'])

function btnPressed() {
emit('clicked_btn')
}
</script>

<template>
    <button @click="btnPressed()">Press me </button>
    <button @click=$"emit('clicked_btn')"></button>
</template>>();

Events

It is advisable that props are never directly reassigned to a  new value within the child component, instead, an event should be emitted to the parent, allowing the parent to manage the property update. As seen in the above example with the emission.

Static vs Dynamic

Props do not necessarily need to be bound, a static prop can also be passed. A bound property is usually used when passing a reactive property to a component:

// bound
const myTitle = ref<String>("My journey through Vue")
<BlogPost :title="myTitle" />
// static
<BlogPost title="My journey with Vue" />

Conditional and list rendering

Conditional rendering

The v-if, v-else-if and v-else statements are used to conditionally render a component, based on the truthy-ness of an expression value.

<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  Not A/B/C
</div>

List rendering

Rendering a specific component several times based on source data. Allows for efficient rendering of components and removes clutter of duplicate elements within the component.

<div v-for="item in items">
  {{ item.text }}
</div>

// or provide ordering hint to force reorder of elements based on given key
<div v-for="item in items" :key="item.id">
  {{ item.text }}
</div>




TailwindCSS Logo




Tailwind CSS

Tailwind CSS 3.4 promotes a utility-first approach, contrasting with the component-first approach of regular CSS. Instead of relying on pre-designed components and styles, Tailwind enables developers to create scalable and reusable designs by combining their utility classes. This eliminates the need for large, hard-to-maintain CSS files.

Seamless integration with Vue and other JavaScript frameworks like React and Angular. While it remains fundamentally CSS, it simplifies development through its intuitive utility classes. Additionally, DaisyUI enhances Tailwind by providing component class names, offering a library of customizable components that can be easily adapted and styled with Tailwind's utility classes.

Optional configuration of color schemes, themes, spacing values, animation, keyframes, etc. through the tailwind.config.js file or as an inline utility class. Allows for project-specific adjustments and styling.

// inline custom value
<div class="top-[117px]">
  <!-- ... -->
</div>

// set custom value for screen sizes and colors in the tailwind config file
module.exports = {
  theme: {
    screens: {
      sm: '480px',
      md: '768px',
      lg: '976px',
      xl: '1440px',
    },
    colors: {
      'blue': '#1fb6ff',
      'pink': '#ff49db',
      'orange': '#ff7849',
      'green': '#13ce66',
      'gray-dark': '#273444',
      'gray': '#8492a6',
      'gray-light': '#d3dce6',
    },
 }
}

Purge functionality to remove unused CSS from the generated utility classes to optimize performance and ensure smaller file sizes.

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

Tailwind allows for responsive design and thus ensures the adaptability of the user interface. By prefixing a utility class with a predefined breakpoint prefix the element will respond when the screen size breakpoint is reached.

<!-- Width of 16 by default, 32 on medium screens, and 48 on large screens -->
<img class="w-16 md:w-32 lg:w-48" src="...">

Summary

Both frameworks provide the utility to develop scalable and efficient web applications but have a learning curve. Once you get used to the specific syntax of props, emissions, utility classes etc. it becomes quite easy to use and create your desired components and styles.

For further and more detailed information please refer to the links in the resource section below, this was a brief and general overview of my experience getting to learn Vue and Tailwind CSS.

Resources:

As a note, this overview gives information for Tailwindcss 3.4. Some of the examples and syntax provided are changed or removed in Tailwindcss 4.1!