How to Build Your Own CSS Preprocessor With PostCSS

Share this article

Use a CSS preprocessor for a while and life soon becomes imaginable without it. Many developers have adopted LESS, Stylus or — the current favorite — Sass. Ideally, you should also be post-processing your CSS using Autoprefixer to add vendor prefixes when required without resorting to mixins or a frameworks such as Compass. Autoprefixer is a plugin for PostCSS; a tool which translates CSS into an object model which can be used to manipulate styles. There are many more plugins available which implement preprocessor-like features such as variables, mixins and nesting. Ben Frain’s recent article, Breaking up with Sass: it’s not you, it’s me, raises an interesting proposition. Do you really need Sass, LESS or Stylus given you can craft the CSS preprocessor you want using PostCSS? A basic Sass-like parser can be created within your build process. For this example, I’ll use a Gulp.js task file but the same concepts apply to Grunt or any other build system. First, we install PostCSS and the plugins we need using npm, e.g.

npm install gulp-postcss postcss-mixins postcss-simple-vars postcss-nested autoprefixer-core --save-dev
then create an array of CSS processing functions in gulpfile.js, e.g.
var
	gulp = require('gulp'),
	postcss = require('gulp-postcss'),
	processors = [
		require('postcss-mixins'),
		require('postcss-simple-vars'),
		require('postcss-nested'),
		require('autoprefixer-core')({ browsers: ['last 2 versions', '> 2%'] })
	];
and write a CSS processing task, e.g.
// compile CSS
gulp.task('css', function() {
  return gulp.src('source/css/styles.css')
    .pipe(postcss(processors))
    .pipe(gulp.dest('dest/styles/'));
});
You can also create your own processing functions using the PostCSS API. For example, we could apply a sans-serif fallback for all font-family declarations:
processors = [
		require('postcss-mixins'),
		require('postcss-simple-vars'),
		require('postcss-nested'),
		function(css) {
			// sans-serif fallback
			css.eachDecl('font-family', function(decl) {
				decl.value = decl.value + ', sans-serif';
			});
		},
		require('autoprefixer-core')({ browsers: ['last 2 versions', '> 2%'] })
	];
If the file /source/css/styles.css
contained this code:
$colorfore: #333;
$colorback: #fff;

@define-mixin reset {
	padding: 0;
	margin: 0;
}

main {
	font-family: Arial;
	@mixin reset;
	color: $colorfore;
	background-color: $colorback;
	
	article {
		color: $colorback;
		background-color: $colorfore;
	}
}
running gulp css would create this CSS in /dest/css/styles.css:
main {
	font-family: Arial, sans-serif;
	padding: 0;
	margin: 0;
	color: #333;
	background-color: #fff;
}

main article {
	color: #fff;
	background-color: #333;
}

The Advantages

PostCSS frees you from the limitations and choices imposed by preprocessor authors. The approach offers several benefits:
  • Modularity
    You need only add the plugins and functions you require for your project.
  • Lightweight
    Preprocessors are increasingly large and sophisticated applications. You probably won’t want or use every feature but they’re still present. PostCSS reduces the bulk.
  • Immediate implementation
    Have you ever waited for something to become available in Sass, LibSass, LESS, Stylus or another preprocessor? You can now develop your own features using…
  • JavaScript functions
    Your CSS preprocessor uses JavaScript — a true programming language (despite what some people say!) Most preprocessor language constructs are basic. You’ll often see functions and mixins which are more complex and difficult to comprehend than the raw CSS they create. With PostCSS, facilities which will never be implemented in Sass/LESS/Stylus are available. You can open files, read from databases, make HTTP requests or create complex calculations with ease.
  • Enforce development policies
    Presume you wanted your team to avoid @extend declarations. It’s no longer possible for anyone to use @extend unless they add an extend plugin to the build process. That would be immediately obvious.
  • It’s fast — very fast
    The authors estimate PostCSS is 4 – 40x faster than an equivalent preprocessor. I suspect the gains are even higher if you only require a few plugins. The whole solution is built in JavaScript and there’s no need to jump into another library or language interpreter.

The Disadvantages

All good then? Unfortunately, PostCSS is not a perfect solution:
  • Increased complexity
    Your build process will become more difficult to manage. Adding Sass is typically a line or two of code but PostCSS requires more planning — especially since plugins must be called in a specific order. For example, @import in-lining should be resolved prior to parsing variables. But what if you have variables within your @import declarations? In some situations it may be necessary to call a plugin more than once.
  • A different syntax
    I initially attempted converting a small Sass project to PostCSS. Don’t even try! While I eventually succeeded, PostCSS plugins often use a slightly different syntax, e.g. @define-mixin rather than @mixin. This could lead to confusion and numerous code updates. Part of the reason…
  • PostCSS requires valid CSS
    Most preprocessors parse plain text files so any syntax is theoretically possible. PostCSS creates an object model so it requires syntactically-correct CSS from the start. Even a // single line comment can cause it to fail. You could pre-process your CSS files before passing to PostCSS but then you’re back to using a preprocessor!

Should You Abandon Your Preprocessor?

A custom PostCSS processor could be an attractive option if you’re in a one-person team embarking on a small, relatively simple self-contained project. I also recommend PostCSS for any genuine post-processing tasks such as vendor prefixing, packing media queries into a single declaration, reducing calc() equations, applying fallbacks for older browsers, supporting CSS4 selectors, minification etc. There’s little benefit doing that work yourself. However, Sass has achieved critical mass. No preprocessor syntax is perfect but it’ll be understood by the majority of developers in your team. Anything subtly different is unlikely to offer significant benefit or appeal to everyone. That said, PostCSS and the similar Rework framework have enormous potential. If a modular CSS plugin system could replicate — and even mix — the syntax and functionality we want from Sass, LESS and Stylus, we would have a single preprocessor to beat all others. You can bet someone, somewhere is working on that project now… Have you successfully used PostCSS as a preprocessor for your project? Has it enticed you away from Sass? Are you going to move on from LESS? Will you give up on Stylus?

Frequently Asked Questions about PostCSS

What is the main difference between PostCSS and other CSS preprocessors?

PostCSS is a tool for transforming styles with JavaScript plugins. These plugins can do various tasks like linting, adding vendor prefixes, and even enabling future CSS features. Unlike other CSS preprocessors like Sass or Less, PostCSS does not have a built-in syntax. Instead, it uses plugins to transform CSS. This makes it more flexible and customizable, as you can choose only the plugins you need for your project.

How do I install and use PostCSS?

To install PostCSS, you need to have Node.js and npm installed on your computer. You can then install PostCSS globally using the command npm install -g postcss-cli. To use PostCSS, you need to install the plugins you want to use and then create a configuration file where you specify the plugins you want to use. You can then run PostCSS on your CSS files using the command postcss input.css -o output.css.

What are some popular PostCSS plugins?

There are many PostCSS plugins available, each serving a different purpose. Some popular ones include Autoprefixer, which automatically adds vendor prefixes to your CSS; cssnext, which allows you to use future CSS features today; and cssnano, which minifies your CSS for production.

Can I use PostCSS with other CSS preprocessors?

Yes, you can use PostCSS alongside other CSS preprocessors like Sass or Less. This allows you to take advantage of the features of these preprocessors, while also benefiting from the flexibility and power of PostCSS.

What are the benefits of using PostCSS?

PostCSS offers several benefits. It’s highly customizable, allowing you to choose only the plugins you need. This can result in a smaller, faster build process. PostCSS also enables you to use future CSS features today, and it can automatically add vendor prefixes to your CSS, saving you time and ensuring your styles work across different browsers.

Are there any drawbacks to using PostCSS?

While PostCSS is powerful and flexible, it can have a steeper learning curve than other CSS preprocessors. Because it relies on plugins, you need to spend time researching and choosing the right plugins for your project. Additionally, because it’s a newer tool, it may not be as well-supported or widely adopted as other preprocessors.

How does PostCSS handle mixins?

PostCSS handles mixins through the postcss-mixins plugin. This plugin allows you to define and use mixins in your CSS, similar to how you would in Sass or Less. You can define a mixin in your PostCSS configuration file and then use it in your CSS with the @mixin keyword.

Can I use PostCSS in my existing project?

Yes, you can integrate PostCSS into your existing project. You just need to install PostCSS and the plugins you want to use, and then set up a PostCSS configuration file. You can then run PostCSS on your existing CSS files.

How does PostCSS compare to other tools like Autoprefixer or cssnext?

Autoprefixer and cssnext are actually PostCSS plugins. This means that they are tools that run on top of PostCSS, taking advantage of its plugin architecture. Autoprefixer adds vendor prefixes to your CSS, while cssnext allows you to use future CSS features today.

Is PostCSS suitable for large projects?

Yes, PostCSS is suitable for projects of any size. Because it’s customizable, you can choose only the plugins you need, resulting in a smaller, faster build process. This makes it a good choice for large projects where performance is a concern.

Craig BucklerCraig Buckler
View Author

Craig is a freelance UK web consultant who built his first page for IE2.0 in 1995. Since that time he's been advocating standards, accessibility, and best-practice HTML5 techniques. He's created enterprise specifications, websites and online applications for companies and organisations including the UK Parliament, the European Parliament, the Department of Energy & Climate Change, Microsoft, and more. He's written more than 1,000 articles for SitePoint and you can find him @craigbuckler.

autoprefixerCSScss preprocessorLESSPostCSSsassStylus
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week