In this post I am going to show you how you can use TailwindCSS and Vue together to create beautiful web-apps without ever leaving your template-tag.
Summary
- Setup Vue 3 with TailwindCSS using Vite
- Creating a vue component
- Using the utility-first workflow
The is also a video for those of you who prefer to watch something over reading.
Setting it all up
For this project you will only need Node.js installed - that's it! After installing that we can create a new vue project using the new build tool called Vitejs - which is blazingly fast, next-generation frontend build tool.
Open a new terminal and navigate to the directory where you would like to install the project.
There you can paste in the following commands:
npm init @vitejs/app <your-project-name>
You will be greeted with this screen in you terminal:
Use the arrow keys to navigate to Vue and hit enter to download the dependencies.
Now select JavaScript:
After hitting enter, this will download all of the necessary dependencies for Vite as well as for Vue.
cd <your-project-name>
To navigate into the created directory and finally:
npm install
Those of you familiar with node modules will know this command pretty well - it will install everything for us.
Select Vue 3 and it will install everything for us - awesome!
Now we can verify that everything works by running npm run dev
to get start up our development server.
If you navigate to http://localhost:3000/ you should see our scaffolded project.
Awesome! That works - now for our tailwind-setup.
First you need to stop the development server - in your terminal use ctrl + c.
Following the steps outlined in the tailwind docs, we first install the necessary packages using npm.
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
Then we create two config files - a posts.config.js-file and a tailwind.config.js-file. The tailwind.config.js-file will house any changes we would like to make to the standard tailwind-configuration.
npx tailwindcss init -p
Lastly, we create a new index.css-file and add in the base tailwind styles:
@tailwind base;
@tailwind components;
@tailwind utilities;
Import your index.css-file in our main.js-file to complete our tailwind-setup:
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
createApp(App).mount('#app')
We can now fire up our development-server to see if there are any errors.
You may see something like this:
While very odd-looking, this indicates to us that tailwind is working and styling our pages for us.
We can create a simple check to see if everything works:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Hello Vue 3 + Vite" />
<h2 class="text-blue-700 text-2xl">Vue, Vite and Tailwind</h2>
</template>
Which will result in:
Perfect! Now to create some components.
Buttons, buttons and more buttons
We are going to create a very simple yet well-loved UI-element: the button.
First remove everything inside the App.vue-file - yes, even the beautifully crafted blue heading we just created.
Now we can create the template-tags which will hold all of our markup and inside that, we will create a button tag without classes for now:
<template>
<div class="mt-5 flex justify-center">
<button>Primary</button>
</div>
</template>
The classes added to the div will simply center the elements inside and push them down a bit from the top.
This results in a very sad button indeed:
I know minimalism is a thing in UX-Design, but I think this is going a bit too far, is it not?
From a UX-Design-perspective this is not a very well-designed button - you would never say simply by looking at it, that this is a button.
Let us help our users out by showing them some button-typical styles:
<template>
<div class="mt-5 flex justify-center">
<button class="bg-indigo-700 text-white">Primary</button>
</div>
</template>
Will result in:
It is not great or even good - it is ok - we need a few more adjustments, the label is too cramped - let us add some padding inside:
<template>
<div class="mt-5 flex justify-center">
<button class="bg-indigo-700 text-white px-8 py-2">Primary</button>
</div>
</template>
Using the px- and py-utilities we can separately control how much space is to the left and to the right of our label, as well as how much space is to the top and to the bottom of the label:
Looking a lot better - now we have a great base to continue.
Let me just round the corners a bit, to make the button appear more friendly:
<template>
<div class="mt-5 flex justify-center">
<button class="bg-indigo-700 text-white px-8 py-2 rounded-md">
Primary
</button>
</div>
</template>
There we go - now let us work on giving the user feedback regarding the state of our button.
Hover, Active and Focus States
A button is more than just a background with text - it can change shape when we hover over it, when we click the button and when it is active.
Tailwind allows us to specify these styles using hover:, focus: and active:.
Let us see how we can add a hover state - let us lighten the background colour of our button:
<template>
<div class="mt-5 flex justify-center">
<button
class="bg-indigo-700 text-white px-8 py-2 rounded-md hover:bg-indigo-500"
>
Primary
</button>
</div>
</template>
We can now see that if we activate the hover state, we see that our background has changed colour:
Awesome!
Now we want to give feedback to the user when the button is clicked - for that we need to configure tailwind.
For this we will open the tailwind-config.js and add the following line:
module.exports = {
purge: [],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {
backgroundColor: ["active"], //allows active-states
},
},
plugins: [],
};
This is how you can extend tailwinds standard configuration to suite your own needs.
Now let us move on to style the button when it is clicked - at the moment, it is still not giving any feedback to the user, when she/he clicks on the button:
<template>
<div class="mt-5 flex justify-center">
<button
class="
bg-indigo-700
text-white
px-8
py-2
rounded-md
hover:bg-indigo-500
active:bg-indigo-900
"
>
Primary
</button>
</div>
</template>
If we click on the button, the background colour becomes darker:
Now for the last part of our button, we can add an focus-style - this is the outline you see around a button when it is clicked. They are generally active by default, but you may well want your own custom look for your app or website.
Now we can add the focus-state to our button:
<template>
<div class="mt-5 flex justify-center">
<button
class="
bg-indigo-700
text-white
px-8
py-2
rounded-md
hover:bg-indigo-500
active:bg-indigo-900
focus:outline-none
focus:ring-2 focus:ring-indigo-700 focus:ring-opacity-50
"
>
Primary
</button>
</div>
</template>
We first remove the standard outline and then using the ring-utilities we can add in our own:
That's it!
What now?
Sad that this post is over?
There is more where this one came from - in the meantime, here are other great resources you can use to quench your thirst for knowledge, such as the Tailwind Docs.
I highly recommend building up on this project we have here and try building form components such as input fields and alerts to further dive into the utility-first workflow.
If you are looking for more information on Vitejs, again I can recommend the Vite documentation.
The Vue 3 documentation is a great place to start, if you are looking to start out with Vue or if you are looking to upgrade your Vue 2.x projects.
If those aren't enough, you can always have a search around online and see what tickles your developer-fancy.
I hope you are inspired to give Tailwind a go in your next side-project, and I will see you soon with another post.
Top comments (0)