Motivation
Having done quite a few front-end development and writing a bunch of CSS codes, I've began to notice the way I write my CSS codes -- I will usually have a few files with a few variables and classes in them. For example, .fc { display: flex; flex-direction: column; }
to quickly have a flex container with a vertical structure. I will also have a bunch of margin-related classes and variables to quickly apply them declaratively on the HTML template.
At the same time, I knew at the back of my head that Tailwind CSS was a thing. It was until recently that it clicked for me. What I was doing with my CSS was actually what made Tailwind CSS so popular. They had a bunch of these classes already written out to declaratively style elements and they did it in a system that is much more scalable than what I was doing.
I immediately wanted to try this out on my next project, which I promised Reassemble that I would create a consumer-facing company website for them. I planned to do a few new things, namely configuring Tailwind CSS and using Contentful, a server-less backend to give them a system to manage the website.
Setting up Tailwind CSS in Nuxt
My first instinct when I saw Tailwind CSS was to understand where the UI kit is. What they are providing was simply a way to style elements, but they did not provide components that can be quickly used. I found Tailwind UI, but it was framework-agnostic. I needed something fast and compatible with Vue immediately. Luckily, I found Vue Tailwind, which uses Tailwind CSS to style the custom components they provide, while providing options for me to override their styles using Tailwind CSS's methods.
1. Add @nuxtjs/tailwindcss
Setting up Vue Tailwind and Tailwind CSS themselves was a little tricky. As a rule of a thumb, I always find the most compatible module or plugin for Nuxt so I don't have to reinvent the wheel. I quickly found Nuxt-tailwind, which provided an easy installation of Tailwind CSS.
# Add @nuxtjs/tailwindcss dependency to your project
npm install --save-dev @nuxtjs/tailwindcss # or yarn add --dev @nuxtjs/tailwindcss
# Add @nuxtjs/tailwindcss to the buildModules of nuxt.config.js file
{
buildModules: [
'@nuxtjs/tailwindcss'
]
}
After adding the dependency, you may need to run your project yarn dev
to trigger the module to create 2 files in your source directory. ~/tailwind.config.js
is for customising Tailwind CSS default properties such as colours, breakpoints and font family. ~/assets/css/tailwind.css
is used to import Tailwind's CSS. I modified it to look like this (using VSCode Vue PostCSS viewer). Note: font-display and font-body are declared in tailwind.config.js
. Refer to Tailwind CSS documentation for this.
/* purgecss start ignore */
// Import your web fonts here.
@tailwind base;
@tailwind components;
// Customise your styles here
// An example is as follows
html {
@apply font-body;
}
.h1,
.h2,
.h3,
.h4,
.h5,
.h6 {
@apply font-display;
}
/* purgecss end ignore */
@tailwind utilities;
2. Add Vue-Tailwind
To have all the basic components ready to go, let's install Vue-Tailwind.
npm install vue-tailwind --save
# or
yarn add vue-tailwind
Create a file in /plugins
called vue-tailwind.js with the following content.
import Vue from 'vue'
import VueTailwind from 'vue-tailwind'
Vue.use(VueTailwind)
Add this plugin to nuxt.config.js
{
plugins: [
{ src: "@/plugins/vue-tailwind" }
]
}
Now that we have vue-tailwind installed, we can proceed to modify the default theme by creating a myOwnTheme.js
file in plugins.
You can style their components like this.
// /plugins/myOwnTheme.js
const TInput = {
// Notice that this will override the full `baseClass` setting so probably you want to keep some
// of the clases and just replace the ones you want to override.
// baseClass: 'border block w-full rounded',
baseClass: 'border-2 border-blue-500 block w-full rounded',
}
const TButton = {
// baseClass: 'border block rounded inline-flex items-center justify-center',
baseClass: 'rounded-lg border block inline-flex items-center justify-center',
// primaryClass: 'text-white bg-blue-500 border-blue-500 hover:bg-blue-600 hover:border-blue-600',
primaryClass: 'text-white bg-purple-500 border-purple-500 hover:bg-purple-600 hover:border-purple-600',
}
const MyOwnTheme = {
TInput,
TButton,
}
export default MyOwnTheme
Import this theme into Vue Tailwind plugin as so.
// plugins/vue-tailwind.js
import Vue from 'vue'
import VueTailwind from 'vue-tailwind'
import MyOwnTheme from '@/plugins/myOwnTheme.js'
Vue.use(VueTailwind, {
theme: MyOwnTheme
})
3. Setting up Purge CSS
Update: With the release of TailwindCSS JIT mode, you can skip this step.
The most important part is how everything can play nicely together. Nuxt-tailwindcss module uses Purge CSS by default, which cause issues with Vue-Tailwind. Purge CSS is not the problem here as it is recommended by Tailwind CSS to reduce the space your app will use.
// nuxt.config.js
{
purgeCSS: {
mode: 'postcss',
extractors: [
{
extractor(content) {
return content.match(/[\w-.:/]+(?<!:)/g)
},
extensions: ['html', 'vue', 'js']
},
{
extractor(content) {
return content.match(/[A-Za-z0-9-_:/]+/g)
},
extensions: ['js']
},
]
}
}
The most important thing here is to set the mode to 'postcss'
and include a new extractor recommended by Vue-Tailwind.
What this does is simple -- it tells purge css to look into any extensions with .js, and match the content with the regex (see 2nd extractor). Since our myOwnTheme.js file has the classes of the components, it'll grab the classes from the .js file instead of the HTML template. From what I understand, since the components are generated dynamically, purge CSS will not be able to find the base/customised classes from our Vue templates to include as part of the build. So, we have to instruct them to find it from the .js file instead.
Conclusion
By doing these steps, we will have a working Tailwind CSS and Vue component to use in our application that is still optimised by Purge CSS. With Tailwind-focused components, the customisations are easy and endless. Neat!