Tailwind class madness. Never again?!
Tags: vue, tailwindcss, typescript, javascript
Published: 2021-09-29 09:17:29

A couple of days ago my sister asked for a favor. She wanted to create a small contact/promo page for the kindergartner’s that she is running. Nothing special and fancy, just a regular landing page with some event graphics and the contact form. Weekend job.

Well, sounds like a very easy and fast task to do and help my sibling in need. First thought was [Vue](https://vuejs.org), the next one was [Tailwind](https://tailwindcss.com). After some further thinking turns out this is a great opportunity to finally use [Vite](https://vitejs.dev) … with the real-life project.

So I do have my tools for UI/frontend part, what's left was the form handler and app deployment, serving platform. And as I can get all of this from [Netlify](https://www.netlify.com/) … the decision was made.

---

Installing and running the Vite was super easy. The performance of this tool is incredible, it's extremely fast and powerful. Turns out that I can play a bit with the [script setup](https://v3.vuejs.org/api/sfc-script-setup.html) concept as well. It "forces" kinda new writing approach but eventually it's very convenient and aligned with the [Composition API](https://v3.vuejs.org/api/composition-api.html) flow.

OK, my development environment is ready now I just need to start creating actual components. As I'm using Tailwind I need to set some initial config with my default style values. You know, font sizes, colors, and other stuff. Fine.

Create containers with some grid classes, great, nothing special here. Time for some global, reusable components like buttons. And here we go... 🤕 Tailwind utility classes madness. To define a simple button I had to use like a' twenty-plus classes. Flashback - every time when I'm using Tailwind I'm dealing with these super long line markups - terrible. Nightmare right?

**This must be ended**! At least for my Vue apps. 😃

---

I know, I can use [apply](https://tailwindcss.com/docs/extracting-components#extracting-component-classes-with-apply) handler and define all the classes in the style section. But this is not solving the problem at all. This is also not so global, "reuse" friendly. So what I need is to define some global variants for my global components like buttons, inputs, blocks. But how to use them with Tailwind and Vue? Easy, as long I can bind my styles inside the Vue templates I can define my styles as an object and use them everywhere. And of course, while I'm using Composition API I can create some fancy composable. That is how the **[vue-use-variant](https://github.com/lukasborawski/vue-use-variant)** package was created.

The main goal was to create the globally accessible object or objects with some style definitions, components variants. Let's do that. For the banner.

```typescript
import { ref } from 'vue'

export const buttonVariants = {
  button: 'font-bold rounded border-0 bg-blue hover:opacity-80',
  buttonPrimary: 'p-4 text-lg',
  buttonSecondary: 'p-2 text-md',
}

export const buttonVariantsRef = ref(buttonVariants)
```

Great. 👍 We have some overall button styles and some variant definitions — for primary and secondary. Typical one. 😅

OK, now the composable and how I’m using it with the above variants.

```vue
<template>
  <button :class="buttonVariant" type="button" />
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
import { buttonVariants, buttonVariantsRef } from './variants.ts'
import { useVariant, UseVariant } from 'vue-use-variant'
export default defineComponent({
  name: 'Button',
  setup() {
    const { defineVariant } = useVariant() as UseVariant
    return {
      buttonVariant: defineVariant(
        ref({
          button: true,
          buttonPrimary: true,
        }),
        buttonVariantsRef,
      ),
    }
  },
})
</script>
```

Your final result will look something like this.

```
font-bold rounded border-0 bg-blue hover:opacity-80 p-4 text-lg
```

That’s it. Awesome right? It’s clean, readable, convenient, fast, and globally available. The class madness has been ended. 🎉 You can use it with **Ref** objects, with **props**, and straight away inside the component. Finally, you can use it with **any other framework**. It was built for the Vue ecosystem but it’s not stopping you to use it with React if you want.

Create your variants for all the reusable components and use them across your application. This way you’ll always get one source of truth and your UI components will always come with the same shape and visual representation.

Find the technical specification and some guidelines [here](https://github.com/lukasborawski/vue-use-variant). You can install it from [npm](https://www.npmjs.com/package/vue-use-variant) or [yarn](https://www.npmjs.com/package/vue-use-variant). You can play with the very basic demo provided inside the repository. It was created with Vite, so that might be the additional stimulant. And of course, any suggestions, issue reports are very warmly welcome.

Thanks for reading. Enjoy! ✋

<a href="https://www.buymeacoffee.com/lukas.borawski" target="_blank"><img src="https://miro.medium.com/max/1400/1*CEZSIxeYr6PCxsN6Gr38MQ.png" alt="Buy Me A Coffee"></a>