DEV Community

Charlie Gerard
Charlie Gerard

Posted on

Writing a TailwindCSS variant plugin

I've been using TailwindCSS for the past few months and wanted to spend some time understanding how to create custom plugins.
I noticed that the CSS pseudo-element :first-line was not available by default in Tailwind so I decided to implement it myself by creating a variant plugin.

When using TailwindCSS, you add a tailwind.config.js file to your codebase where you specify different settings, themes, etc.
It's also in this file that you can add plugins.

To get started, you need to add a function inside the plugins property of your config file.

// tailwind.config.js
plugins: [
    plugin(({ addVariant, e }) => {
Enter fullscreen mode Exit fullscreen mode

The addVariant is a helper function to register custom variants and e is for escaping strings meant to be used in class names.

Inside this plugin function is where you need to write the logic.

In the end, I'd like to be able to write classes with the following syntax: first-line:text-red. This would set the color of the first line of an element to red, for example.

By default, text-red works but sets the color of the whole element, so how can we make the prefix first-line: work?

Here's the full code sample that I'll explain below.

addVariant("first-line", ({ modifySelectors, separator }) => {
  modifySelectors(({ className }) => {
    const newClass = e(`first-line${separator}${className}`);
    return `.${newClass}:first-line`;
Enter fullscreen mode Exit fullscreen mode

In addVariant, I specify the name of my variant, here first-line.

Then, we need to use the modifySelectors function, and the separator option that lets you customise what character or string should be used to separate variant prefixes, in our case :.

Inside modifySelectors, we have access to the class that first-line is applied to.

As we want to be able to write first-line:text-red, when the plugin detects that first-line is used, the separator is : and the className is text-red.

Then, this function returns this entire class and appends :first-line to target the first line of the element, the same way you would write it using vanilla CSS.

This way, the className generated in the end is .first-line\:text-red:first-line. Tailwind does its magic to use the color red, and this variant makes sure it's only applied to the first line of the element it's applied to. 🎉

And that's it! 🙂 If you'd like to have a look at the source code, you can find it on Github.

Top comments (0)