PostCSS Deep Dive: Create Your Own Plugin

PostCSS Deep Dive: Create Your Own Plugin

As I’m sure you’ve well and truly gathered by this point, what makes PostCSS amazing is its thriving plugin ecosystem. And a huge reason there are so many great plugins, with more coming out all the time, is that PostCSS makes creating your own plugin so accessible for anyone who has some experience with JavaScript.

You don’t need special permission to make a PostCSS plugin; if you want to make one, you just go right ahead and make it. Through this freedom you have the ability to turn your CSS development processes into anything you want them to be, not to mention the opportunity to share your work with other members of the rapidly growing PostCSS community.

In this tutorial you’ll learn how to create a basic plugin of your own for PostCSS. We won’t be going too heavily into the plugin API, and we won’t use any super hardcore coding. I myself am a front-end developer, and my JavaScript skills are at the level you would expect them to be for a front-end person, yet that didn’t stop me making my first PostCSS plugin in just a few hours.

Follow along and see for yourself just how approachable PostCSS plugin development can be!

What We’re Going to Build

We’ll be creating a plugin that allows for easy insertion of font stacks into  declarations via the following syntax:

After compilation, the above code will turn into:

Set Up a Project to Work Inside

Even though you’re creating your own plugin, you’ll still need to start by creating an empty Gulp or Grunt project. You’ll be loading your plugin into this project in the same way you’ve been using other people’s plugins throughout this series.

You can read about how to set up Gulp or Grunt projects for PostCSS in the previous tutorials:

If you don’t want to manually set up your project from scratch, though, you can download the source files attached to this tutorial, and extract either the provided Gulp or Grunt starter project into an empty project folder. Then, with a terminal or command prompt pointed at the folder, run the command .

Create a Basic Plugin Shell

Create a folder in “node_modules” named “postcss-myplugin”. It’s common to use the prefix to make it clear your plugin is for PostCSS.

All PostCSS plugins are node modules, so we’ll need to turn your new folder into one. Open up a terminal/command prompt, pointed at the newly created folder, and run . This will perform the basic setup of a node module, so just follow the prompts that come up in your terminal, leaving the “entry point” field as the default “index.js”.

When this is done, with your terminal still pointed at the folder, run the command . This will install PostCSS as a dependency for this module, something all PostCSS plugins need to do.

Create a file named “index.js” in the “postcss-myplugin” folder. Add this code to load in the main postcss module:


Then below it add this basic wrapper that will surround our plugin’s processing code: 

Load Your New Plugin

Now we’re ready to load your newly created plugin into your project. It won’t do anything yet, but we just want to get the essential setup in place.

Load the Plugin via Gulp

If you're using Gulp, add this variable under the one already in the file:

Now add the new variable name into your  array:

Do a quick test that everything is working by running the command  and checking that a new “style.css” file has appeared in your project’s “dest” folder.

Load the Plugin via Grunt

If you're using Grunt, update the  object, which is nested under the  object, to the following:


Do a quick test that everything is working by running the command  and checking that a new “style.css” file has appeared in your project’s “dest” folder.

Add the Plugin Functionality

Add Test CSS

Before we start adding processing code to our plugin, we’re going to add some test code to our stylesheet that the plugin can work on.

To your “src/style.css” file add this CSS:


Right now, because our plugin isn’t doing anything yet, if you compile your CSS you’ll just see exactly the same code copied straight into your “dest” folder's “style.css” file.

Loop Through the Rules and Declarations

Now we want to start scanning the CSS of our file so we can find any instances of and process them. To get started on this, add the following code after the  line:

Using walkRules() in the first line iterates through every rule in your CSS; a rule is basically your selector and the styles you’ve set between its curly braces. In our test CSS a rule would be:


Then, inside each rule, walkDecls() iterates through every declaration; a declaration is essentially each line in the style. In the above CSS, a declaration would be:

 

Check if  Syntax Is Used

As we iterate through each declaration using the code we just added, the current declaration is represented by , which gives us access to both the declaration’s property and its value via and respectively.

With our example CSS,  would give us  and would give us .

We want to check every in our stylesheet to see if it contains the string. If it does, we know someone is trying to use our plugin to add a font stack to their CSS.

Inside the loop, add:

First we’re taking and storing it in the variable . Any changes to will be sent into the compiled stylesheet; we’re storing its contents in the variable so we can mess around with it.

Then we’re using the indexOf() method to search our new variable for the string . If it’s found, we’re logging “found fontstack” to the console so we can check if everything is working thus far.

Run or and you should see “found fontstack” output once in your terminal/command prompt.

Define Some Fontstacks

Now that our plugin is able to locate instances of  in our stylesheet, we can get ready to convert that instance into a font stack, i.e. a list of font names. But before we can do that, we need to first define these font stacks.

At the top of your file, under the existing variable, create a variable named. We’re going to turn this variable into an object containing key-value pairs.

For each entry in the object, the key should be the first font in the font stack, e.g.. It will be the string a user passes to specify the font stack they want to use, e.g. or .

The value in each pair should be a string of the full list of fonts contained in the font stack, e.g. .

Add two entries to your object, one for 'Arial' and one for 'Times New Roman', using the font stacks provided by CSS Font Stack.


Your variable should look like this:

Check Which Fontstack Is Requested

The first thing we need to do when we find an instance of being used is to figure out which font stack the user has requested, i.e. what string they have set between the brackets. 

For example, if a user entered we would want to extract the string . The reason we want this string is it will give us a key we can use to look up the corresponding font stack from our object.

Add this code immediately inside the statement we added earlier, replacing the  line:

We are performing two steps here to extract the name of the fontstack as a string.

First we use the match() method to find whatever string is between the brackets in our value. This would give us a string like  or .

We only want the font name, without any double or single quotes, so we then use the replace() method to strip them from the string, leaving us with an unquoted string such as .

This string is stored in the variable.

Title Case the Requested Fontstack

We’re going to use our newly created variable to look up a font stack from our option. The tricky part is the keys in this object are case sensitive, so if we try to look up the entry with the key it will fail.

To solve this, we’re going to “Title Case” the string, so for example would be converted to . We’ll be doing this via a short custom function.

Under your variable add this function:

Now we’ll apply this function to our variable. Under the line where you created the  variable, add this code:

This passes the variable through our function, updating its value.

Lookup Fontstack From Config

Now we have our variable set correctly, we can use it to look up the corresponding font stack. After the line you just added, insert this code:

This finds the value in the object that has a key matching the string contained in our variable. 

For example, if contains the string , the entry in with the key  will be found and the value  will be returned.

This returned value is then stored in the variable .

Check for Fonts Set Before fontstack()

Now we have our font stack string retrieved and ready to be inserted into the CSS, but there’s still one more thing we need to do. You’ll recall in our test code we included the font "Open Sans" as the preferred font, with the font stack acting as a fallback. We also need to retrieve this font name from the value so it can be added to the CSS we insert into the processed stylesheet.

Below the variable line, add this code:

This code uses the substr() method to find any content between the beginning of our, (represented by 0), and our instance (located by using theindexOf() method). Whatever content is found is stored in the variable .

For example, in our test code  is equal to , so the variable will be set as .

Create a New Value

We now have all the pieces we need to create a new value with which to replace our test code’s original value of .

After the last code you added, insert this code:

Here we’re combining our and variables into a single string and storing it in the variable . 

In our test code, this would mean combining  and .

Our  variable would then hold the string .

This now gives us the complete value that we want to add into the processed stylesheet so that: 

... is transformed into:

Send the New Value Back to the Stylesheet

Now that we have our new value ready to be inserted into the processed stylesheet, all we have to do is update . PostCSS will take care of the rest, adding the new value into the processed CSS for us.

Add this code after the last line you added:

This sets  to equal the content of our variable.

Test Your Plugin

Your plugin is now good to go. Give it a whirl by compiling your stylesheet with or  (with your terminal pointed at your project folder, not your plugin folder).

Your “dest/style.css” file should now show a complete font stack:

(Optional) Add User-Configurable Fontstacks Options

You may wish to allow users of your plugin to set their own options, in the same way you have been setting options as you’ve used PostCSS plugins throughout this series.

We want users to be able to set a option, either adding extra font stacks or redefining existing font stacks, for example:

Note: this step is optional. If you wish you can skip it and your plugin will work perfectly fine, just without any user set configuration.

We already have the most essential part of enabling user set options in place in our plugin. In our line you’ll notice an argument is being passed. 

We’ll receive any user options a user sets through this.

You’ll also see we have the line:

This checks to see if has any value, and if it doesn’t, sets it to an empty object. This makes sure we don’t get any errors when we start working with that might come from it being undefined.

To get started, we’re going to install Underscore.js into our project, as we’ll be using its handy extend() method. Run this command to install it into the plugin you’re building:

Now load Underscore into your plugin by adding an variable to require it, under your existing variable:

Next what we’re going to do is take the object we already created inside the plugin, and “extend” it with any font stacks the user has set through their options configuration.

Add this code directly under the  line:

The option that has been set by the user is represented by.

By using Underscore’s method, all the font stacks in are added to those already in . Wherever there is a matching key, the value from will overwrite the one in. This allows users to redefine any existing font stacks.

In your Gulpfile or Gruntfile, set a option and pass a new font stack as well as redefining an existing one:

Now add some extra CSS to your “src/style.css” file so we can test the new font stack we just added via our options:

 

Recompile your CSS and you should see that your 'Arial' font stack now has different output, and that your 'Extra Stack' font stack has output correctly:

Your Completed Plugin

That’s it! You’re all done. You’ve completed your first PostCSS plugin.

Here’s the entire thing on GitHub should you need to compare your code to it for reference.

Let’s Recap

You’ve just created an entire PostCSS plugin, and I hope some ideas are springing into your mind about other plugins you’d love to make. Maybe there’s that one little thing that’s always bugged you when writing CSS, and perhaps now you can come up with your own solution to get rid of it for good. Or maybe there’s something extra you really think CSS ought to have out of the box—well, now you can add it in for yourself!

To sum up what we’ve covered:

  • Start developing a new plugin by setting up a Gulp or Grunt project to work in.
  • Create a new node module inside your project, which will become your plugin.
  • Load your new plugin into your project.
  • Add some test CSS in the syntax you want your plugin to use.
  • Use methods from the PostCSS API to scan through a stylesheet.
  • Locate instances of your plugin's syntax being used.
  • Write JavaScript and use the PostCSS API to make the appropriate transformations (and/or additions) to the original code and send it into the processed CSS.

To view or add a comment, sign in

Others also viewed

Explore content categories