Setting up Tailwind with Vue.js
Tags: vue, tailwindcss
Published: 2021-04-02 23:20:27

---
title: Setting up Tailwind with Vue.js
published: true
description: In this guide, you will add Tailwind to a Vue application. to improve the layout for our blog pages. You will go through dependencies, configuration, and component creation. To follow this tutorial you will need a basic understanding of Vue
tags: Vue, Tailwind
cover_image: https://cdn.sanity.io/images/81pocpw8/production/8ca491da800f86a3679bd62bc2bcd3417f7a2ae0-2400x1800.jpg
canonical_url: https://www.sanity.io/guides/tailwind-css-with-vue-js
---
## Summary

In this guide, you will add Tailwind to a Vue application to improve the layout for our blog pages. You will go through dependencies, configuration, and component creation. To follow this tutorial you will need a basic understanding of Vue.  

### Why use TailwindCSS?

In 2019‚ and even more so in 2020, [Tailwind CSS](https://tailwindcss.com/) exploded in popularity when developers saw the potential in a design system that was more like an API. Unlike Bootstrap, which provides pre-built components, Tailwind CSS provides utility classes to build your own components that are completely responsive and let developers create exactly what they need. Tailwind and Vue integrate together with just a few packages, making it a go-to option for any developer. 

### What are utility classes?

Utility classes are single purpose classes which are self descriptive in nature, unlike traditional CSS classes. For example:

```css
.flex: {
	display: flex
}
```

This example describes that you are adding flex, and only adds display flex to an element. This makes it reusable anywhere in the code and know exactly what it does. 

### Finished project link

To follow along exactly with the blog post you can find the repository on my GitHub by clicking this 

[link](https://github.com/perkinsjr/vue-with-tailwindcss/commit/9dbab69ee2ea32abbda44c1c1bf65b99b2a89c70).

## Setup

Add the dependencies 

To begin with, you need to install the dependencies for Tailwind. Inside your terminal or command prompt, from the root of your project, type the following:

```bash
npm install tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
```

First, you are probably wondering why you are versioning, well there is (as of April 2021) a compatibility issue between `tailwindcss` and `postcss` which you can read about [here](https://github.com/tailwindlabs/tailwindcss/discussions/2854). So what do these dependencies do? Let's break them down:

**tailwindcss :** Contains all the Tailwind code that you can use in our Vue application.

**[postcss](https://postcss.org/) :** PostCSS is used to transform CSS using a variety of JS plugins, it's a one stop-shop for being able to lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more.

**[autoprefixer](https://github.com/postcss/autoprefixer#readme) :** AutoPrefixer is a plugin for postCSS that parses all of your CSS and adds the vendor prefixes to your CSS rules. This means you don't have to worry whether you are using Microsoft Edge , Firefox, or Chrome!

### Creating Tailwind configuration files

Now you have all of the dependencies installed you need to create two configuration files that will handle both what happens with PostCSS and any configuration you want to make with Tailwind such as themes, dark mode etc. At the root of your project create a `tailwind.config.js` and `postcss.config.js` and let's take a deep dive into what you have, first let's open the newly created `tailwind.config.js` file and create our default configuration:

```jsx
// ./tailwind.config.js
module.exports = {
  purge: [],
  darkMode: false,
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}
```

Tailwind is built on the premise of building customized user interfaces from the ground up, in this file you can create a whole theme, use plugins, set default colors and so much more. In this tutorial, you will be using the purge option only. The purge option allows you to put in all of your files that contain CSS and as part of the build step will removed any used styles. You can learn more about configuring Tailwind in the configuration [documentation](https://tailwindcss.com/docs/configuration). Let's move on to the `postcss.config.js` file and enter the following :

```jsx
// ./postcss.config.js
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}
```

As mentioned earlier, you use PostCSS to transform CSS using a variety of JS plugins, in this case when our code is built PostCSS will handle both Tailwind CSS and any prefixes for browsers without any intervention from us!

### **Configure Tailwind to remove any unused styles in production**

The final piece of our configuration is to have Tailwind purge any unused styles when in production to keep our bundle size as small as possible, to do this open up your `tailwind.config.js` file and type the following:

```jsx
// ./tailwind.config.js
module.exports = {
   purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
    darkMode: false,
    theme: {
      extend: {},
    },
    variants: {
      extend: {},
    },
    plugins: [],
  }
```

What you are doing here is telling Tailwind where the paths to all our components and pages so Tailwind can remove all unused styles using a technique called [tree-shaking](https://en.wikipedia.org/wiki/Tree_shaking), which deletes all the unused styles.

### Adding Tailwind to our CSS

Now that you have installed and set up everything required to start using Tailwind you need to create a way to use it globally. So let's create an `index.css` in your `src` folder to hold our Tailwind styles:

```css
<!-- ./src/main.css -->
@tailwind base;
@tailwind components;
@tailwind utilities;
```

This might seem like you are going to have every single Tailwind style in our application but at build time Tailwind is smart enough to styles generated based upon your configuration. 

### Import your CSS file into main.js

The final setup piece is to import the CSS file into our `main.js` which is located at `./src/main.js` and once imported your file should look like: 

```jsx
// ./src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'

createApp(App).mount('#app')
```

Tailwind is now set up and referenced, so you are ready to create a great looking blog page. 

If you are following along here is the [commit](https://github.com/perkinsjr/vue-with-tailwindcss/commit/ed6b236f76419366051035ab5c096c22fc3f35c5) 

## Creating Components

For this tutorial, you are going to create a navigation bar and a blog page which will be our home page, the blog posts won't actually exist but it will give you a great starting point for your own blog post. 

### Creating a Navigation Bar.

Let's begin by creating a responsive navigation header that you can use on each page. Let's have create some starter code that doesn't have any Tailwind attached, create a new component called `NavBar`:

```html
<!--./src/components/NavBar.vue -->
<template>
  <header>
    <div>
      <nav>
        <ul>
          <li><router-link to="/">Home</router-link></li>
          <li><router-link to="/">Blog</router-link></li>
          <li><router-link to="about">About</router-link></li>
        </ul>
      </nav>
    </div>
  </header>
</template>

<script>
export default {
  name: "NavBar",
};
</script>
```

Now you have this new `NavBar` component let's use it in our application by adding it to our `App.vue` file. Inside the `App.vue` file remove the original `div` above the `router-view`  below is the before and after:

```html
<!-- ./src/App.vue -->

<!--before -->
<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </div>
    <router-view/>
  </div>
</template>

<!-- after --> 
<template>
  <div id="app">
    <router-view />
  </div>
</template>
```

You are now ready to place use our own `NavBar` component. To import a Component you need to add a `script` tag under our template and then register the template copy the code below : 

```jsx
// ./src/App.vue
...
<script type="text/javascript">
import NavBar from "@/components/NavBar.vue";
export default {
  components: {
    NavBar, // register component
  },
};
</script>
```

Then you can add this into our template, so before the `router-view` add in the `NavBar`  so your finished code should look like the following:

```jsx
// ./src/App.vue
<template>
  <div id="app">
    <NavBar />
    <router-view />
  </div>
</template>

<script type="text/javascript">
import NavBar from "@/components/NavBar.vue";
export default {
  components: {
    NavBar, // register component
  },
};
</script>
```

Now launch your code and navigate to [`localhost:8080`](http://localhost:8080) and you should see the following:

![NavBar](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yademaz9hbeiff9ivoet.png)

It doesn't look great but the links to `Home` and `About` work as expected so let's add some Tailwind to this to make a navigation bar with responsiveness! 

### Adding Tailwind to our component

Open up your `NavBar` component and let's start adding some classes from Tailwind, first you want to add a border to the bottom to add some division, and then you will add some flex to our surrounding `div`: 

```jsx
// ./src/components/NavBar.vue
<template>
  <header class="border-b">
    <div
      class="container flex flex-col flex-wrap p-5  md:items-center md:flex-row"
    >
....
```

So let's explain what is happening here, 

- Under the header, you are adding a `class="border-b"` which is a border on the bottom.
- Then in the `div`  you are adding the `container` class.
- Adding `flex` and any screen, bigger than medium size will be `flex-col` with `flex wrap`.
- Adding `p-5` which adds `padding: 1.25rem`

 

The part  `md:items-center md:flex-row` means when the size reduces to a breakpoint for medium screens, it will center the items and make them into a row. You can read about responsive designs and conditional breakpoints in the link below:

[https://tailwindcss.com/docs/responsive-design](https://tailwindcss.com/docs/responsive-design)

Next, you can add `flex` to our `<ul>` and some margin and font styles to our links to make sure you have a functional and responsive Navbar. 

```jsx
// ./src/components/NavBar.vue
<ul class="flex flex-wrap items-center justify-center text-base ">
          <li class="mr-5 text-sm font-semibold hover:text-gray-800">
            <router-link to="/">Home</router-link>
          </li>
```

So this code, allows the items to wrap as needed, and on the individual items you are adding a margin on the right, making the font bold and changing the state when you hover over them, at this point your code should look like the following: 

```jsx
// ./src/components/NavBar.vue
<template>
  <header class="border-b">
    <div
      class="container flex flex-col flex-wrap p-5  md:items-center md:flex-row "
    >
      <nav>
        <ul class="flex flex-wrap items-center justify-center text-base ">
          <li class="mr-5 text-sm font-semibold hover:text-gray-800">
            <router-link to="/">Home</router-link>
          </li>
          <li class="mr-5 text-sm font-semibold hover:text-gray-800">
            <router-link to="/">Blog</router-link>
          </li>
          <li class="mr-5 text-sm font-semibold hover:text-gray-800">
            <router-link to="about">About</router-link>
          </li>
        </ul>
      </nav>
    </div>
  </header>
</template>

<script>
export default {
  name: "NavBar",
};
</script>
```

If you are following along here is the [commit](https://github.com/perkinsjr/vue-with-tailwindcss/commit/40407ef742b0256111e449f586a20d18b745832b).

You should now have a navbar that looks like this on your desktop:

![Desktop Version of Nav](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xx69dqyr7qdp8k1noaa.png)

Then when you shrink the screen size down and hit the media point you should now have a navbar that looks like: 

![Smaller Version of Nav](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/un3jnxdhl778x6odyxhk.png)

Looking pretty good! A nice `NavBar` component to help our users navigate our website. 

### Creating the blog post page

As I explained previously, you aren't creating any blog posts but you can create a "fake" Blog page that will show the user a cover image, title, and excerpt. To make this easier below is the code will be using but first let's create a new component called `BlogPage` which will handle that in our components directory. 

```html
<!-- ./src/components/BlogPage.vue -->
<template>
  <div id="blog-home">
    <h1>Thoughts and Posts</h1>
    <div>
      <article>
        <figure>
          <img src="http://via.placeholder.com/250x250" alt="" />
        </figure>
        <h2>A blog post about my dog</h2>
        <p>Super awesome doggo, with a great smile.</p>
      </article>
    </div>
    <div>
      <article class="media">
        <figure>
          <img src="http://via.placeholder.com/250x250" alt="" />
        </figure>
        <h2>Post about some code we wrote</h2>
        <p>Sometimes coding is very hard, and othertimes it's very easy</p>
      </article>
    </div>
    <div>
      <article class="media">
        <figure>
          <img src="http://via.placeholder.com/250x250" alt="" />
        </figure>
        <h2>Titles are hard to think of.</h2>
        <p>Just like naming variables, naming title are hard.</p>
      </article>
    </div>
  </div>
</template>
```

This has three basic blog posts with a title, image holder and a short excerpt, you now have a `component` but you need to create a `route` and `view` so our users can navigate. Create a new file inside your views folder called `Blog.vue`, this will handle what is displayed to the user when they navigate to the route. 

The view template will be simple because you created a `component` and don't have to worry about creating any more `HTML` so below is the template part

```html
<!-- ./src/views/Blog.vue-->
<template>
  <div class="blog">
    <BlogPage />
  </div>
</template>
```

Similar to `App.vue` you are registering the component to use it. Now you need to add a route to our routes file, which is located under `router` named `index.js` . To add the router you can copy the about route.

Now you need to import the `BlogPage` component and reference it so you can actually use it in our view.

```html
<!-- ./src/views/Blog.vue-->
...
<script>
import BlogPage from "@/components/BlogPage.vue";

export default {
  name: "Blog",
  components: {
    BlogPage,
  },
};
</script>
```

```html
<!-- ./src/router/index.js -->
{
    path: "/blog",
    name: "Blog",
    component: () => import(/* webpackChunkName: "blog" */ "../views/Blog.vue"),
  },
```

If you are following along you can check out this [commit](https://github.com/perkinsjr/vue-with-tailwindcss/commit/1b6a1dd51b092e8d58d9e4cf6c271b1b3c16d9e4). 

Go ahead and launch your application and navigate to [`http://locahost:8080/blog`](http://localhost:8080/blog) and you should now see the following: 

![Post before Responsive](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1bufe7ay562ftu54diql.png)

This is not pretty or responsive, so let's start adding our Tailwind to make a blog post page look great! 

### Adding Tailwind to the blog post.

So you are going to create a grid style blog page where each post takes up 1/3 of the width of the screen. To begin with let's center our Heading and increase the size and add a margin to the top: 

```html
<!--./src/components/BlogPage.vue-->
<template>
  <div id="blog-home">
    <h1 class="text-center text-xl mt-4">Thoughts and Posts</h1>
...

```

This will give our heading a nice centered look and increase the size. 

![Heading](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ju9ree6o8spah0ud85sc.png)

Now you can create a container using the next `main` and add some padding around the top and sides. 

```html
<!--./src/components/BlogPage.vue-->
<template>
  <div id="blog">
    <h1 class="text-center text-xl mt-4">Thoughts and Posts</h1>
    <main class="container px-8 pt-24 mx-auto lg:px-4">
.....
```

This gives us the container class padding on the sides and top, margin on the x-axis to auto and on large screens, you will also at padding on the x-axis. 

You now need to add an additional `div` surrounding our article, which will handle flex for us. So create a new `div` and add the classes `flex flex-wrap`. 

```html
<!--./src/components/BlogPage.vue-->
<template>
  <div id="blog">
    <h1 class="text-center text-xl mt-4">Thoughts and Posts</h1>
    <main class="container px-8 pt-24 mx-auto lg:px-4">
      <div class="flex flex-wrap">
....
```

Now you have our container, and flex `div` you can start working on our articles, now in the real world, you would only need to create a single one and loop over all of your articles. So I will show you how to create a single version of it, and then I will show you a complete version.

On our `article` tag let's add the classes for padding, and width for both large screens and the default sizing.

```html
<!--./src/components/BlogPage.vue-->
<article class="px-8 py-6 lg:w-1/3 md:w-full">
```

This will add padding on the sides and top and bottom, on a large screen it will take 1/3 of the width and on smaller than large screens it will create a full width, this will allow us to create a column effect when the screen is smaller. 

You can now add padding to the `div` that contains all of our blog post information: 

```html
<!--./src/components/BlogPage.vue-->
<article class="px-8 py-6 lg:w-1/3 md:w-full">
          <div class="p-6 rounded-md">
...
```

Now for our cover image you are going to make the image rounded also and specific height so no matter what size image it will always look great! 

```html
<article class="px-8 py-6 lg:w-1/3 md:w-full">
          <div class="p-6 rounded-md">
            <img
              class="object-cover object-center w-full h-40 mb-6 rounded"
              src="http://via.placeholder.com/250x250"
              alt="content"
            />
```

So you are creating a full width and height of `h-40` (10rem) you are also using `object-cover` which will make the image cover the container. Finally you are rounding the corners, your images should now look like:

![Rounded Corner Images](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0p71mgxvzc1sbd9pfj0m.png)

For our blog title will will make the the text have a margin on the bottom and the text larger so it pops for our users: 

 

```html

<article class="px-8 py-6 lg:w-1/3 md:w-full">
          <div class="p-6 rounded-md">
            <img
              class="object-cover object-center w-full h-40 mb-6 rounded"
              src="http://via.placeholder.com/250x250"
              alt="content"
            />
            <h2 class="mb-3 text-lg lg:text-2xl">
              A blog post about my dog
            </h2>
```

As you can see for any screen it should have large text, and only on large screen it should be 2xl, now you just need to take care of our excerpt and link to read more. 

To handle our paragraph that is an excerpt you are going to use `leading-relaxed` which actually means you are going to a `1.25 rem` to our line height and you will add a margin at the bottom also. 

```html
<!--./src/components/BlogPage.vue-->
<article class="px-8 py-6 lg:w-1/3 md:w-full">
          <div class="p-6 rounded-md">
            <img
              class="object-cover object-center w-full h-40 mb-6 rounded"
              src="http://via.placeholder.com/250x250"
              alt="content"
            />
            <h2 class="mb-3 text-lg lg:text-2xl">
              A blog post about my dog
            </h2>
            <p class="mb-4 leading-relaxed">
              Super awesome doggo, with a great smile.
            </p>
```

So the final piece to the puzzle is the link to `"read more"` , you are going to add some hover color change and then add some margin on the bottom, you are also going to make it `inline-flex` and center the items. 

 

```html
<article class="px-8 py-6 lg:w-1/3 md:w-full">
          <div class="p-6 rounded-md">
            <img
              class="object-cover object-center w-full h-40 mb-6 rounded"
              src="http://via.placeholder.com/250x250"
              alt="content"
            />
            <h2 class="mb-3 text-lg lg:text-2xl">
              A blog post about my dog
            </h2>
            <p class="mb-4 leading-relaxed">
              Super awesome doggo, with a great smile.
            </p>
            <a
              href="#"
              class="inline-flex items-center md:mb-2 lg:mb-0 hover:text-blue-400 "
            >
              Read More
            </a>
          </div>
        </article>
```

You now have a complete `article` , so you can find the final commit [here](https://github.com/perkinsjr/vue-with-tailwindcss/commit/8a320dbbd8b9f14f3857a4ce1d9383351928dde3). 

If you launch your application you should now see the following: 

![Desktop Complete](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9oy0bmydvtn1gfjpo4h.png)

and on mobile you will see this:

![Mobile Complete](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ofexbgwpdgzckk87qmel.png)

## Conclusion

You have now come to the end of our tutorial and created a blog page example using Tailwind, if you have been coding along while reading you would have learnt the following: 

1. Learnt how to install TailwindCSS and PostCSS and setup our Vue application to use them.
2. Create a responsive Navigation Bar that allows your end users to navigate regardless of the size of their screen.
3. Create a fully responsive Blog page with styled images, headings and excerpts and the option to read more. 

Now you have a good base layer, you can start adding your own post to your Vue application and explore using the ability to create your own [themes](https://tailwindcss.com/docs/theme).