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%);
}
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
}),
]
}
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%)`
}
}
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);
})
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)
this is awesome