Using Tailwind plugins to create custom utility classes
Tags: css, tailwindcss, javascript, typescript
Published: 2024-04-22 07:44:37

I can't imagine working right now without TailwindCSS. At first, I thought that it is just another CSS library like hundreds before but the thing with Tailwind is that it does exactly what we as developers love -> achieve same results with less steps.

If you think even about the simplest examples like aligning the text center, in normal CSS you would do:

```html
<div style="text-align: center;">Hello World</div>
```

With Tailwind, you can achieve the same with:

```html
<div class="text-center">Hello World</div>
```

It may not seem like that big of a change, but if you multiply such small DX improvements by the amount of classes and styles you will write in your application, adding Tailwind to your project will allow you to save a lot of time.

But do remember that TailwindCSS does not give you a vendor lock in. It is not a library that would help you speed up development and afterwards, make project maintenance a hell like some libraries. 

In this article however, I wont be talking about these simple built in classes as this is a rather basic and well explained topic but I will explain to you a concept that I have encountered recently when I tried to create custom classes with IDE autocomplete and style highlight. So, in this article, we will be talking about Tailwind plugins that will allow use to create custom class utilities/helpers.

Enjoy!

## 🤔 What is a Tailwind Plugin?

In general, plugins let you register new styles for Tailwind to inject into the user’s stylesheet using JavaScript instead of CSS.

The most basic example of a Tailwind plugin looks like following:

```ts
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities, addComponents, e, config }) {
      // Add your custom styles here
    }),
  ]
}
```

To get started with plugins, import Tailwind’s plugin function from tailwindcss/plugin. Then inside your plugins array, call the imported plugin function with an anonymous function as the first argument.

Plugin functions receive a single object argument that can be destructured into several helper functions:

* `addUtilities()`, for registering new static utility styles
* `matchUtilities()`, for registering new dynamic utility styles
* `addComponents()`, for registering new static component styles
* `matchComponents()`, for registering new dynamic component styles
* `addBase()`, for registering new base styles
* `addVariant()`, for registering custom static variants
* `matchVariant()`, for registering custom dynamic variants
* `theme()`, for looking up values in the user’s theme configuration
* `config()`, for looking up values in the user’s Tailwind configuration
* `corePlugins()`, for checking if a core plugin is enabled
* `e()`, for manually escaping strings meant to be used in class names

To learn more about plugins, check out https://tailwindcss.com/docs/plugins

## 🟢 Using Tailwind Plugins to create custom classes

In this example, I want to showcase a recent addition to one of my projects where we wanted to add custom utility classes to handle our own Typography. 

To create your custom plugin, let'f first create a new file called `typography.ts`. In it, let's paste following code:

```ts
import plugin from 'tailwindcss/plugin';

export default plugin(({ addComponents, theme }) => {
  addComponents({
    // Headings
    '.typography-heading3': {
      fontSize: theme('fontSize.lg'),
      lineHeight: '26px',
      fontFamily: theme('fontFamily.heading'),
      fontWeight: theme('fontWeight.semibold'),
      '@screen md': {
        fontSize: '24px',
        lineHeight: '32px',
      },
    },
    // more custom utility classes
});
```

Here, we are importing the plugin from the tailwindcss library and below, exporting this plugin so that it can be easily imported by the tailwind config file. Next, we are destructuring the `addComponents` and `theme` utils and we are using both below to create the new utility class.

The `theme` utility helper is really useful if you want to use values that are already available in the theme configuration to reuse code. Keep in mind, that the plugin approach uses the CSS in JS concept.

As a bonus, you can also see here how we can handle styles that are only meant to be displayed for certain devices :)

Next, in the `tailwind.config.js` file, let's import this plugin like following:

```ts
const typographyPlugin = require('./src/styles/typography');

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
  plugins: [typographyPlugin],
};
```

And that's it! We can now use this utility class in our application and have full Tailwind autocompletion and style highlight like following:

![Tailwind Plugin class highlight](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/evc09s7wz6fif59bcdea.png)

This has proven to be really useful not only for Typography but also for other elements related to UI of our application.

## 📖 Learn more 

If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this [link](https://vueschool.io/courses?friend=baroshem) or by clicking the image below:

[![Vue School Link](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i662jpyni4zs2dlaeud1.png)](https://vueschool.io/courses?friend=baroshem)

It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉

## ✅ Summary

Well done! You have just learned how to use Tailwind plugins to create custom classes. 

Take care and see you next time!

And happy coding as always 🖥️