Building Vue 3 components with Tailwind CSS
Tags: engineering
Published: 2023-03-06 09:37:45

---
title: Building Vue 3 components with Tailwind CSS
published: true
date: 2023-02-21 18:03:04 UTC
tags: Engineering
canonical_url: https://snyk.io/blog/building-vue-3-components-tailwind-css/
---

[Vue](https://vuejs.org/) is a popular JavaScript framework for building versatile web interfaces. Some of its most compelling features are its easy integration into existing code-bases and lightweight framework, making it easy for developers to start using in their frontend projects.

At the core of Vue is a composable component approach to building UI web applications. Components are reusable pieces of code that you can use as the building blocks of your applications. Vue’s component model enables you to build self-contained components with logic, content, and styles in a single location.

When styling these components, you can use a framework like [Tailwind CSS](https://tailwindcss.com/) to include the styles directly in the markup, encapsulating the component even further. Tailwind CSS is a CSS framework that incorporates reusable classes for styling user interface (UI) elements. You can use these classes to apply stylistic elements like fonts, colors, padding, margins, animations, and transitions. For example, using a `text-black` attribute will display all of an element’s text in black. These classes are composable, and you can combine them to implement any design.

In this tutorial, you’ll learn how to build Vue 3 components with Tailwind CSS by creating a responsive article card component. The complete project code is available [here](https://github.com/snyk-snippets/vue-tailwind3-best-practices).

### Prerequisites

To follow along, you’ll need:

- An up-to-date version of Node.js and [npm](https://docs.npmjs.com/cli/v7/configuring-npm/install) installed
- A text editor like Visual Studio Code (VS Code)
- Knowledge of the command line
- Familiarity with Vue and CSS

## Creating your own Vue 3 components with Tailwind

To begin, create a new Vue 3 project. Run the following command in your terminal to install and execute [create-vue](https://github.com/vuejs/create-vue), the official Vue project scaffolding tool for building [vite](https://snyk.io/advisor/npm-package/vite)-powered projects:

```
npm init vue@latest
```

You should receive a prompt with a list of optional features. Name the project `vue-tailwindcss` and choose `No` for the rest of the options.

```
√ Project name: ... vue-tailwindcss
√ Add TypeScript? ... No / Yes
√ Add JSX Support? ... No / Yes
√ Add Vue Router for Single Page Application development? ... No / Yes
√ Add Pinia for state management? ... No / Yes
√ Add Vitest for Unit Testing? ... No / Yes
√ Add an End-to-End Testing Solution? » No
√ Add ESLint for code quality? ... No / Yes
√ Add Prettier for code formatting? ... No / Yes
```

Now, navigate to the project folder using `cd vue-tailwindcss` and run `npm install` to install the project’s open source dependencies from npm.

Execute `npm run dev` to start the application in a development environment.

This command should start the app on the localhost server:

![](https://snyk.io/wp-content/uploads/blog-vue-tailwind-localhost.jpg)

Navigate to the indicated local URL to view the app:

![](https://snyk.io/wp-content/uploads/blog-vue-tailwind-you-did-it.jpg)

Now it’s time to set up Tailwind CSS in the Vue app.

## How to set up Tailwind with Vue

To begin, run the following command in the terminal:

```
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
```

This command installs Tailwind CSS and its peer dependencies (`autoprefixer` and `postcss`) via npm.

Next, generate your `tailwind.config.js` and `postcss.config.js` files by running the command below. You’ll use these files to configure and customize Tailwind:

```
npx tailwindcss init -p
```

This command should create `tailwind.config.js` at the project root with these details:

```
   module.exports = {
   content: [],
   theme: {
     extend: {},
   },
   plugins: [],
 }
```

You also created `postcss.config.js` and configured the `tailwindcss` and `autoprefixer` plugins:

```
  module.exports = {
   plugins: {
     tailwindcss: {},
     autoprefixer: {},
   },
 }
```

In `tailwind.config.js`, modify the content array to include all the paths to your pages and components. This will configure Tailwind to remove unused CSS classes from the final output, reducing the file size. 

Your `tailwind.config.js` file should now look like this:

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

Next, create a new file named `index.css` in the `src` folder of the project and add the following:

```
@tailwind base;
@tailwind components;
@tailwind utilities;
```

You used the `@tailwind` directive to include Tailwind’s base, components, and utilities styles in your project. Later, when you build the project, Tailwind will automatically replace these directives with the styles you dictated to it.

Now, import `index.css` into our `./src/main.js` file to start using it:

```
import './index.css'
```

Note that you should delete the line importing the `assets/main.css` file. This will prevent you from using vanilla CSS.

You can now start creating components using Tailwind.

## How to create Vue components

To learn how to use Tailwind in Vue components, create a card component for an article.

Then, create a new file named `ArticleCard.vue` in the `src/components` folder. Add the following code:

```
<template>
  <div>
    <div>
      <img src="../assets/coverimage.jpg" alt="Close-up of code" />
    </div>
    <div>
      <div>Vue</div>
      <a href="#">Building Vue 3 Components With Tailwind CSS</a>
      <p>
        Learn how to create visually stunning Vue components using the popular
        utility-first CSS framework Tailwind.
      </p>
    </div>
  </div>
</template>
```

The code above creates a template named `ArticleCard`, which defines a card component consisting of an image and an informational blurb about the article.

To display it in-browser, clean up the homepage by deleting everything in the `App.vue` file. Then, import the `ArticleCard` component into the script section of `App.vue`:

```
<script setup>
import ArticleCard from "./components/ArticleCard.vue";
</script>
```

Then, use it in the template:

```
<template>
  <ArticleCard />
</template>
```

The next step is to style the card using Tailwind CSS utility classes.

### Utility classes explained

With vanilla CSS — and a few other CSS frameworks — you can use custom CSS classes to style elements on a page.

Here’s an example of a link element styled with the link-wrapper and link classes:

```
<template>
  <div class="link-wrapper">
    <a href="#" class="link">Building Vue 3 Components With Tailwind CSS</a>
  </div>
</template>
<style>
.link-wrapper {
  padding: 8px;
}
.link {
  font-weight: 500;
  font-size: 1.125rem;
  line-height: 1.75rem;
  color: #000;
}
</style>
```

### Why use Tailwind CSS?

The problem with this approach is that you must generate meaningful class names every time you need to style an element. Alternatively, you need to remember an extremely long, descriptive name whenever you want to reuse a class. You also must write significant amounts of CSS, as each class name you add to a page has accompanying styles. So, as your application grows, the CSS files also grow, contributing to an increased bundle size and leading to slow loading times.

However, in Tailwind CSS, you can use predefined CSS classes called utility classes. Utility classes provide common styling options like flex, text-alignment, border, margin, padding, and color. These options enable you to style pages without writing CSS.

Let’s see what the previous link example would look like when styled with Tailwind CSS:

```
<div class="p-8">
    <a href="#" class="font-medium text-lg text-black">Vue + TailwindCSS</a>
</div>
```

You now replaced the style object and the custom classes with the following utility classes:

- `p-8` sets the padding to 8px.
- `font-medium` sets the font weight to 500px.
- `text-xl` sets the font size to 1.125rem and the line height to 1.75rem.
- `text-black` sets the text color to black.

Using utility classes reduces the amount of CSS and makes it easier for anyone looking at the code to understand the intention of the styled elements without referring to a stylesheet.

Tailwind offers a variety of utility classes, which you can find in their [utilities documentation](https://tailwindcss.com/docs/utility-first).

## Styling a card component with Tailwind CSS

Now that you’re familiar with utility classes, it’s time to style the card component.

Start by modifying the `src/components/ArticleCard.vue` file to use Tailwind’s utility classes:

```
<template>
  <div class="flex max-w-2xl mx-auto bg-white rounded-sm shadow-md">
    <div>
      <img
        class="h-full w-full object-cover"
        src="../assets/coverimage.jpg"
        alt="Closeup code"
      />
    </div>
    <div class="p-8">
      <div class="uppercase tracking-wide text-sm text-violet-500 font-medium">
        Vue
      </div>
      <a
        href="#"
        class="mt-1 text-lg tracking-tight font-medium text-black hover:underline"
        >Building Vue 3 Components With Tailwind CSS
      </a>
      <p class="mt-2 text-sm text-slate-500">
        Learn how to create visually stunning Vue components using the popular
        utility-first CSS framework Tailwind.
      </p>
    </div>
  </div>
</template>
```

With the new styles, the card component should look like this:

![](https://snyk.io/wp-content/uploads/blog-vue-tailwind-component-card-2.jpg)

In addition to the utility classes, you used modifiers to style the card. Note the `hover:underline` class of the `<a/>` tag, where hover is the modifier.

In Tailwind, use modifiers at the beginning of a utility class name to describe the state you want to target. In the example above, you targeted the hover case, but you could also target the focus state using the `focus:text-violet-200` class or the active state using `active:text-violet-600`. 

You can use various Tailwind CSS modifiers depending on the condition you want to target. For the full list, check out the [Tailwind CSS documentation](https://tailwindcss.com/docs/hover-focus-and-other-states).

So far, the card component looks great on larger screens, but as you reduce the screen size, it appears increasingly crowded:

![](https://snyk.io/wp-content/uploads/blog-vue-tailwind-card-reduced-size.jpg)

Fortunately, you can change the card layout based on screen width.

### How to handle breakpoints in Tailwind CSS

Tailwind CSS allows you to conditionally apply a utility class at different breakpoints. By default, there are five breakpoints, each taking effect at certain minimum widths:

- `sm` — 640px
- `md` — 768px
- `lg` — 1024px
- `xl` — 1280px
- `2xl` — 1536px

To handle a breakpoint, prefix the utility class with the breakpoint, followed by a colon (`:`).

```
breakpoint:utility-class
```

Consider the following button:

```
<button class="w-16 md:w-32 lg:w-48">
  Submit
</button>
```

Tailwind applies the `w-16` class for small screens, `w-32` for medium screens, and `w-48` for large screens.

You can use breakpoints to change the layout, size, color, or any other property without using media queries. You can also customize the screen sizes inside `tailwind.config.js` if the default sizes don’t meet your design needs.

For example, the following code will override the `lg` screen size:

```
module.exports = {
  theme: {
    extend: {
      screens: {
        'lg': '960px',
      },
    },
  },
}
```

In your article card component, use breakpoints to change the layout of the card and adjust the image size:

Below is the modified code. Note the first `<div/>` and `<img/>` tags:

```
<template>
  <div
    class="md:flex md:max-w-2xl max-w-md mx-auto bg-white rounded-sm shadow-md overflow-hidden"
  >
    <div>
      <img
        class="h-48 w-full object-cover md:h-full"
        src="../assets/coverimage.jpg"
        alt="Closeup code"
      />
    </div>
    <div class="p-8">
      <div class="uppercase tracking-wide text-sm text-violet-500 font-medium">
        Vue
      </div>
      <a
        href="#"
        class="mt-1 text-lg tracking-tight font-medium text-black hover:underline"
        >Building Vue 3 Components With Tailwind CSS</a
      >
      <p class="mt-2 text-sm text-slate-500">
        Learn how to create visually stunning Vue components using the popular
        utility-first CSS framework Tailwind.
      </p>
    </div>
  </div>
</template>
```

Here are the changes you’ve made:

- The `md:flex` and `md:max-w-2xl` modifiers convert the card component to a flex container with a maximum width of 48 rem on medium and large screens. On small screens, the `max-w-md` class sets this width to 28 rem.
- In the `<img/>` element, `md:h-full` displays the image at full height on medium and large screens, and the `h-48` class sets the height to 12 rem on smaller screens.

The resulting component looks like this on a small screen:

![](https://snyk.io/wp-content/uploads/blog-vue-small-screen-card.jpg)

That’s it! You can now build Vue components using Tailwind CSS.

Once you’ve finished creating a Vue application, you can learn [how to deploy it on Netlify](https://snyk.io/blog/how-to-deploy-a-vue-js-jamstack-application-on-netlify/) with automatic security updates from Snyk. Create a free account and import your project to Snyk today to find and fix any vulnerabilities that may be hiding in your project’s dependencies — and protect your application from XSS and other security threats.

## Conclusion

This tutorial showed you how to build a Vue 3 component using Tailwind CSS. Tailwind CSS is a utility-first framework that allows for a more efficient and streamlined workflow for building UI components. You can use utility classes to create responsive designs without referring to external stylesheets or remembering dozens of class names. Tailwind enables you to create your own design system by customizing default classes. Furthermore, it automatically removes all unused classes from the production build, helping you add less code to the final product.