How to create a Tailwind plugin

6 minute read | a year ago

In this tutorial I will be showing you how to create a Tailwind plugin. Tailwind plugins allow you to create CSS in JavaScript instead of relying on the normal way of creating CSS in Tailwind. With that out of the way, lets get started.

At first, we need to go to our tailwind.config.js file, and import the plugin like this.

//tailwind.config.js const plugin = require('tailwindcss/plugin')

Now what we need to do next is the create a property called plugins in our exported object, and assign it an array. Now, inside the array, we need to add a function called plugin. This function takes a function as its first argument. At this point, the code will look something like this.

import plugin from "tailwindcss/plugin"; /** @type {import('tailwindcss').Config} */ export default { content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], theme: { extend: {}, }, plugins: [ plugin(function () { }), ], };

The function passed to the plugin as an argument receives an object. The object contains the following.

  1. addComponents()
  2. addUtilities()
  3. e()
  4. addBase()
  5. theme()
  6. config()
  7. addVariants()
  8. variants()
  9. postcss()

- addComponents(): This method is used for registering static styles for components, such as cards, buttons, etc.

- addUtilities(): This method is used for registering utility styles such as bg-red-500, text-zinc-500, font-medium, etc .

- e(): This method is used for escaping class names e.g. e(`rotate-${key}`). Where key represents a dynamic value.

- addBase(): This method is used for setting default styles on elements like anchor tags. It is also used for resetting element styles.

- theme(): This method is used for looking up themes in the users theme configuration. The code below will generate the following { '1/4': '90deg', '1/2': '180deg', '3/4': '270deg' }

import plugin from "tailwindcss/plugin"; /** @type {import('tailwindcss').Config} */ export default { content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], theme: { extend: {}, rotate: { '1/4': '90deg', '1/2': '180deg', '3/4': '270deg' }, }, plugins: [ plugin(function ({theme}) { console.log(theme("rotate")) }) ] }

- config(): This method is used for looking up values in the users tailwind configuration.

- addVariants(): This method is used for adding variants. E.g responsive variants like 'sm', 'md', 'lg', 'xl', etc.

- variants(): This method is used for looking up variants in the users variants configuration.

- postcss(): This method is used for low level css manipulation with PostCSS.

However, in this tutorial we will be dealing with only the addUtilities(), config() and e(). To create our first utility class, we will declare a varible in the the function, and assign it an object. Inside the object is where we will implement our logic. The property name will be the class name, and the value will be the style to apply on the element. So the code will look like this.

import plugin from "tailwindcss/plugin"; /** @type {import('tailwindcss').Config} */ export default { content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], theme: { extend: {}, }, plugins: [ plugin(function ({ addUtilities }) { const newUtilities = { '.backgroundColor': { backgroundColor: 'blue' } } addUtilities(newUtilities) }) ] }

Basically, what we did is to create a variable called newUtilities and assigned it an object as it's value. Inside the object we have a property called .backgroundColor, this is the class name. The value assigned to backgroundColor will be the style to apply on the element.

Now, we can use the style on our webpage like this.

<div className="backgroundColor w-52 h-52"> <p>Hello Background</p> </div>

Another example. Normally, in tailwind when we want to color text, we normally write it like this text-red-200, text-red-300, text-red-400, text-red-500, etc. Lets say we want to shorten these class names to something like t-r-1, t-r-2, t-r-3, t-r-4, t-r-5, etc. To do this, the first thing we need to do is to import colors from tailwindcss/colors like this.

const colors = require('tailwindcss/colors')

Now what we need to do is to create utilities like this.

plugin(function ({ addUtilities }) { const textColors = { '.t-r-1': { color: colors.red["100"] }, '.t-r-2': { color: colors.red["200"] }, '.t-r-3': { color: colors.red["300"] }, '.t-r-4': { color: colors.red["400"] }, '.t-r-5': { color: colors.red["500"] }, '.t-r-6': { color: colors.red["600"] }, '.t-r-7': { color: colors.red["700"] }, '.t-r-8': { color: colors.red["800"] }, '.t-r-9': { color: colors.red["900"] } } addUtilities(textColors) })

The final code is below. In the next step, we will update the code, and make it even better.

import plugin from "tailwindcss/plugin"; const colors = require('tailwindcss/colors') /** @type {import('tailwindcss').Config} */ export default { content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], theme: { extend: {}, }, plugins: [ plugin(function ({ addUtilities }) { const textColors = { '.t-r-1': { color: colors.red["100"] }, '.t-r-2': { color: colors.red["200"] }, '.t-r-3': { color: colors.red["300"] }, '.t-r-4': { color: colors.red["400"] }, '.t-r-5': { color: colors.red["500"] }, '.t-r-6': { color: colors.red["600"] }, '.t-r-7': { color: colors.red["700"] }, '.t-r-8': { color: colors.red["800"] }, '.t-r-9': { color: colors.red["900"] } } addUtilities(textColors) }) ] }

Now, let's simplify our code further, by making use of the e() and config(). Instead of declaring the colors one by one directly in the textColors object, we can add it to our theme like this.

theme: { extend: {}, colors: { 'r-1': colors.red['100'], 'r-2': colors.red['200'], 'r-3': colors.red['300'], 'r-4': colors.red['400'], 'r-5': colors.red['500'], 'r-6': colors.red['600'], 'r-7': colors.red['700'], 'r-8': colors.red['800'], 'r-9': colors.red['900'], }, }

Next, we need to access the colors from the theme, and map through them using map from lodash. To install map from lodash run the following.

npm i lodash.map

With lodash.map installed, we will be able to generate dynamic class names and values, with the help of config() and e(). Now, the code will look like this.

const textColors = _map(config('theme.colors'), (value, key) => { return { [`.${e(`t-${key}`)}`]: { color: value } } }); addUtilities(textColors)

The overall code looks like this.

import _map from "lodash.map" import plugin from "tailwindcss/plugin"; const colors = require('tailwindcss/colors') /** @type {import('tailwindcss').Config} */ export default { content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], theme: { extend: {}, colors: { 'r-1': colors.red['100'], 'r-2': colors.red['200'], 'r-3': colors.red['300'], 'r-4': colors.red['400'], 'r-5': colors.red['500'], 'r-6': colors.red['600'], 'r-7': colors.red['700'], 'r-8': colors.red['800'], 'r-9': colors.red['900'], }, }, plugins: [ plugin(function ({ addUtilities, e, config }) { const textColors = _map(config('theme.colors'), (value, key) => { return { [`.${e(`t-${key}`)}`]: { color: value } } }); addUtilities(textColors) }) ] }

Optionally, we can extract the plugin into its own file.

//plugins/colors.js import _map from "lodash.map" import plugin from "tailwindcss/plugin"; module.exports = plugin(function ({ addUtilities, e, config }) { const textColors = _map(config('theme.colors'), (value, key) => { return { [`.${e(`t-${key}`)}`]: { color: value } } }); addUtilities(textColors) })

We can import it like we do with other plugins.

//tailwind.config.js const colors = require('tailwindcss/colors') /** @type {import('tailwindcss').Config} */ export default { content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], theme: { extend: {}, colors: { 'r-1': colors.red['100'], 'r-2': colors.red['200'], 'r-3': colors.red['300'], 'r-4': colors.red['400'], 'r-5': colors.red['500'], 'r-6': colors.red['600'], 'r-7': colors.red['700'], 'r-8': colors.red['800'], 'r-9': colors.red['900'], }, }, plugins: [ require("./plugins/colors") ] }

Congratulations on creating your own plugin.

Happy coding...