CSS preprocessors are popular, but they have some drawbacks. In this introduction to PostCSS, we’ll explore the advantages of PostCSS, how it works, and what its extensive range of plugins can achieve.
The Value and Limitations of Preprocessors
Table of Contents
Most CSS developers are familiar with preprocessors. Tools including Sass, Less, and Stylus introduced concepts such as file partials, nesting, variables, and mixins. Some features are gradually appearing in native CSS, but a preprocessor is still useful for managing large codebases and maintaining style and coding consistency.
It may be difficult to imagine life without a CSS preprocessor, but there are downsides:
Preprocessors are not extendable or limitable. Most preprocessors are a black box which provide you a specific set of supported features. It may be possible to write custom functions, but functionality beyond the scope of that tool is remains impossible — such as inlining an SVG as a background image.
Similarly, you can’t stop developers using options you’d rather avoid such as
@extend
or deep nesting. Linting can help, but it won’t stop the preprocessor compiling a valid file.Preprocessors provide their own syntax. Preprocessor code may resemble CSS, but no browser can parse the file natively. The syntax is different and, if your tool changes or is unavailable, your code will require updates to make it usable.
The benefits more than outweigh these risks, but there is an alternative …
What is PostCSS?
PostCSS is not a preprocessor (although it can behave like one). It’s a Node.js tool which takes valid CSS and enhances it. Even those using Sass, Less, or Stylus often run a PostCSS step after the initial CSS compilation. You may have encountered the PostCSS Autoprefixer plugin which automatically prepends -webkit
, -moz
, and -ms
vendor prefixes to CSS properties which require them.
On its own, PostCSS does nothing. It’s a parser which tokenizes CSS code to create an abstract syntax tree. A plugin can process this tree and update properties accordingly. Once all plugins have completed their work, PostCSS reformats everything back into a string and outputs to a CSS file.
Around 350 plugins are available, and most perform a single task such as inlining @import declarations, simplifying calc() functions, handling image assets, syntax linting, minifying, and more. A more user friendly plugin search is available at the PostCSS plugins catalogue.
PostCSS benefits include:
You start with standard CSS. PostCSS is to CSS what Babel is to JavaScript. It can take a standard stylesheet which works in recent browsers and output CSS which works everywhere — for example, transpiling the newer inset property back into
top
,bottom
,left
, andright
properties. Over time, you could drop this process as more browsers supportinset
.Admittedly, some plugins allow you to parse preprocessor-like syntax which isn’t standard CSS, but you don’t have to use them.
Use the plugins and features you need. PostCSS is configurable, and you can adopt the plugins you require. For example, you could support partials and nesting but not permit variables, loops, mixins, maps, and other features available in Sass.
Provide a custom configuration for every project. A individual project configuration can enhance or reduce the set of plugins used elsewhere. The options are far more varied than any preprocessor.
Write your own PostCSS plugins. A wide range of plugins is available for extending syntax, parsing future properties, adding fallbacks, optimizing code, processing colors, images, fonts, and even writing CSS in other languages such as Spanish and Russian.
In the unlikely event you can’t find what you need, you can write your own PostCSS plugin in JavaScript.
You’re possibly using PostCSS already. You may be able to remove your preprocessor dependencies if you’re already running a PostCSS plugin such as AutoPrefixer. PostCSS is not necessarily faster or more lightweight than using a preprocessor, but it can handle all CSS processing in a single step.
Installing PostCSS
PostCSS requires Node.js, but this tutorial demonstrates how to install and run PostCSS from any folder — even those that aren’t Node.js projects. You can also use PostCSS from webpack, Parcel, Gulp.js, and other tools, but we’ll stick to the command line.
Install PostCSS globally on your system by running the following:
npm install -g postcss-cli
Ensure it’s working by entering this:
postcss --help
Installing Your First PostCSS Plugin
You’ll require at least one plugin to do anything practical. The PostCSS import plugin is a good option which inlines all @import
declarations and merges your CSS into a single file. Install it globally like so:
npm install -g postcss-import
To test this plugin, open or create a new project folder such as cssproject
, then create a src
subfolder for your source files. Create a main.css
file to load all partials:
/* src/main.css */ @import '_reset'; @import '_elements';
Then create a _reset.css
file in the same folder:
/* src/reset.css */ * { padding: 0; margin: 0; }
Follow this with an _elements.css
file:
/* src/elements.css */ body { font-family: sans-serif; } label { user-select: none; }
Run PostCSS from the project’s root folder by passing the input CSS file, a list of plugins to --use
, and an --output
filename:
postcss ./src/main.css --use postcss-import --output ./styles.css
If you don’t have any errors, the following code will be output to a new styles.css
file in the project root:
/* src/main.css */ /* src/reset.css */ * { padding: 0; margin: 0; } /* src/elements.css */ body { font-family: sans-serif; } label { user-select: none; } /* sourceMappingURL=data:application/json;base64,...
Note that PostCSS can output CSS files anywhere, but the output folder must exist; it will not create the folder structure for you.
Continue reading An Introduction to PostCSS on SitePoint.