DEV Community

Juhana Jauhiainen
Juhana Jauhiainen

Posted on • Originally published at juhanajauhiainen.com

A Tailwind CSS plugin for adding gradient masks

Some time ago I added excerpts to my blog. A small sample of the full blog text is now shown on the front page after the post heading, date, and tags. To make the excerpts look a bit nicer, I wanted to add an effect that makes the text fade into the background.

You can do this with the CSS mask-image property by setting its value to a linear-gradient.

.some-class {
  mask-image: linear-gradient(to top, rgba(0, 0, 0, 1.0) 0%, transparent 100%);
}
Enter fullscreen mode Exit fullscreen mode

I use Tailwind CSS to style my blog so I wanted to find a solution which doesn't require adding CSS classes or files to my project.

After I didn't find a solution I decided this would be a good time to learn how to make Tailwind CSS plugins.

Creating the plugin was straight forward. I started by reading Tailwind documentation on writing plugins. Then I opened Tailwind Playground and added the plugin skeleton from Tailwind documentation to the config.

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

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

I was only adding utilities, so I removed addComponents, e, prefix, and config from the parameters. In the function body, I added my code for generating the CSS. I wanted to do all combinations of directions (top, right, bottom, left) and the ability to select the linear gradients start percentage. The percentages would go from 0% to 100% with 10% intervals.

Adding utilities with a plugin works by creating a JavaScript object with all the utility class names as attributes and the matching CSS as the values of those attributes.

So for a utility class of gradient-mask-tr-50%, I wanted to generate the following object

{
  "gradient-mask-tr-50%": {
      maskImage: `linear-gradient(to top right, rgba(0, 0, 0, 1.0) 50%, transparent 100%)`
  }
}
Enter fullscreen mode Exit fullscreen mode

The plugin has the directions and gradient steps configured as arrays. The code then uses a reduce function to loop through the directions and steps to generate the classes and CSS rules. The returned object is then passed to addUtilities. Here's the full source code listing of the plugin.

plugin(function ({ addUtilities }) {
  const directions = {
    t: "to top",
    tr: "to top right",
    r: "to right",
    br: "to bottom right",
    b: "to bottom",
    bl: "to bottom left",
    l: "to left",
    tl: "to top left",
  };

  const steps = [
    "0%",
    "10%",
    "20%",
    "30%",
    "40%",
    "50%",
    "60%",
    "70%",
    "80%",
    "90%",
  ];

  const utilities = Object.entries(directions).reduce(
    (result, [shorthand, direction]) => {
      const variants = steps.map((step) => {
        const className = `.gradient-mask-${shorthand}-${step}`;
        return {
          [className]: {
            maskImage: `linear-gradient(${direction}, rgba(0, 0, 0, 1.0) ${step}, transparent 100%)`,
          },
        };
      });

      const stepClasses = Object.assign(...variants);
      return {
        ...result,
        ...stepClasses,
      };
    },
    {}
  );

  addUtilities(utilities);
})
Enter fullscreen mode Exit fullscreen mode

Feel free to try the plugin in this Tailwind Playground.

The next step was to create an installable npm package of the plugin code. I created a new npm project with npm init and copied my plugin code from the playground to a new file called index.js. It has a module.exports definition which contains my plugin function.

I had some confusion on what the module should export, because the plugins I checked didn't use Tailwinds plugin function, but instead wrapped the plugin function into another anonymous function. In the end, I realized the correct way for me was to export the result of calling the plugin function with my plugin code as a parameter.

Other than that, I added a readme with description and instructions and published the package to npm using npm publish.

The full source code can be found from the plugins GitHub repository.

Developing a Tailwind plugin was a simple process, especially because I could test the plugin with the playground before starting a project locally.

If you have any feedback on the plugin, you can add an issue in Github or send me a message in Twitter.

Top comments (1)

Collapse
 
anthonygushu profile image
Anthony Gushu

this is awesome