PostCSS – Transforming Your CSS with JavaScript

postcss

When it comes to CSS, there are always new tools being introduced to help us transform styles in a more fast and efficient manner. In 2013, PostCSS was released but it wasn’t until mid-2015 when a lot of buzz really started to take place in the development community around PostCSS. Today, in 2018, PostCSS is still widely used in the development community and the project itself is still actively maintained by a large community of contributors.

So today we thought we would give you a brief introduction on what PostCSS is and how you can utilize it to streamline your development workflow. Make sure to also check out our previous post where we discussed some of the differences between CSS preprocessors, Sass vs LESS.

What is PostCSS?

PostCSS was developed by Andrey Sitnik, also the author of Autoprefixer, as a means to use JavaScript (mainly with plugins) for CSS processing and/or transforming styles. It is commonly referred to as a postprocessor, but others sometimes refer to PostCSS as a preprocessor. In the end, David Clark sums it up quite nicely.

Note that neither the tool itself nor the plugin ecosystem are direct analogues to Sass and LESS. However: bundle up a set of related plugins that transform author-friendly stylesheets into browser-friendly CSS, and then you have something analogous to the good ol’ “preprocessors.”

No matter what you call it, it is important to know the differences and how it works. PostCSS isn’t necessarily a replacement for Sass or LESS. You can still use your favorite preprocessor and then use PostCSS processing with plugins (although this might complicate your workflow rather than simplify it). PostCSS, the tool itself, is basically just an API which allows you to talk to the PostCSS plugins. These plugins can lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more. Think of it as a very modular setup.

PostCSS has definitely become very popular among developers over the past couple of years. You can see below that on npm, the number of downloads per day has steadily increased. And in total, there have been 382,709,316 downloads just between Jan 1, 2018 and Sept 30, 2018.

postcss npm stats 2018

And if we take a look at Google Trends for “PostCSS” there was a large upward trend from 2015-2016 which has now stabilized from 2016 onward.

postcss google trends 2018

The Drawbacks of Traditional Preprocessors

There are a few drawbacks or limitations that come with traditional preprocessors like Sass, LESS, Stylus, etc. These include:

  • Most preprocessors don’t aim to be compatible with W3C standards.
  • Maintaining a library of Sass or LESS snippets can become cumbersome and leave your project with a bunch of unused code.
  • Preprocessors aren’t extendable therefore if you need something more than what it offers, you’re required to add another step in your build process.

Advantages to Using PostCSS

Once you have mastered CSS there are many advantages to using PostCSS versus that of a preprocessor or using nothing at all. First off, it definitely helps extend CSS in a brand new way using custom syntaxes and properties. One of the biggest advantages though is probably using the plugin ecosystem that accompanies it. There are more than 200 plugins, view a full list here.

Some other advantages of using PostCSS include being able to more easily extend functionality with the ability to create your own plugin and custom functions. You can then transform your CSS into whatever you personally require and use that in your workflow.

Another advantage is that PostCSS is incredibly fast. You probably won’t notice this in compiling, but it is worth mentioning.

PostCSS:   36 ms
libsass:   110 ms  (3.0 times slower)
Less:      157 ms  (4.3 times slower)
Stylus:    286 ms  (7.9 times slower)
Ruby Sass: 1092 ms (30.1 times slower)

PostCSS also uses modules, which means your naming syntax becomes much easier. In this example you can see the input and output.

CSS Input

.name {
  color: gray;
}

CSS Ouput

.Logo__name__SVK0g {
  color: gray;
}

And lastly, you can avoid more errors in your CSS because it enforces consistent conventions with stylelint. See example below.

CSS Input

a { 
  color: #d3;
}

CSS Ouput

app.css
2:10 Invalid hex color

Difference Between PostCSS and Preprocessor

In case you were wondering, here is an example of how PostCSS differs slightly from say that of the Sass preprocessor. Normally with Sass, you use a function like rem to do a unit conversion.

/* input */
.selector { margin-bottom: rem(20px); }

/* output, assuming base font size is 1rem */
.selector { margin-bottom: 1.25rem; }

With the PostCSS postcss-pxtorem plugin we no longer even have to use the function in our code and it automatically does the unit conversion for us.

/* input */
.selector { margin-bottom: 20px; }

/* output, assuming base font size is 1rem */
.selector { margin-bottom: 1.25rem; }

Getting Started with PostCSS

If you have ever used Grunt or Gulp tasks then getting started with PostCSS will be fairly easy for you. It is pretty much a two-step process to get started:

  1. Add the PostCSS extensions for whatever build tool you are using in your workflow, whether this be Gulp, Grunt, etc.
  2. Select from the many plugins available and add them to your PostCSS process.

Gulp

To setup PostCSS with Gulp, you can run the following command. This is using gulp-postcss. And of course you will need Node.js, NPM, and Git installed.

$ npm install --save-dev gulp-postcss

Then install your separate PostCSS plugins. Example of usage below.

var postcss = require('gulp-postcss');
var gulp = require('gulp');
var autoprefixer = require('autoprefixer');
var cssnano = require('cssnano');

gulp.task('css', function () {
    var processors = [
        autoprefixer({browsers: ['last 1 version']}),
        cssnano(),
    ];
    return gulp.src('./src/*.css')
        .pipe(postcss(processors))
        .pipe(gulp.dest('./dest'));
});

Grunt

To setup PostCSS with Grunt you can run the following command. This is using grunt-postcss.  And of course you will need Node.js, NPM, and Git installed.

npm install grunt-postcss --save-dev

Once the plugin has been installed, you need to enable it inside your Grunt file:

grunt.loadNpmTasks('grunt-postcss');

Then install your separate PostCSS plugins. Example of usage below.

$ npm install grunt-postcss pixrem autoprefixer cssnano
grunt.initConfig({
  postcss: {
    options: {
      map: true, // inline sourcemaps

      // or
      map: {
          inline: false, // save all sourcemaps as separate files...
          annotation: 'dist/css/maps/' // ...to the specified directory
      },

      processors: [
        require('pixrem')(), // add fallbacks for rem units
        require('autoprefixer')({browsers: 'last 2 versions'}), // add vendor prefixes
        require('cssnano')() // minify the result
      ]
    },
    dist: {
      src: 'css/*.css'
    }
  }
});

PostCSS Examples

Below are a couple examples using popular PostCSS plugins so you can see how it is transforming the CSS.

autoprefixer

Here is an example of using the autoprefixer PostCSS plugin. This plugin is pretty neat because it parses your CSS and adds vendor prefixes to the CSS rules using values from Can I Use. No more having to remember all the random browser rules.

CSS Input

.example {
 display: flex;
 transition: all .5s;
 user-select: none;
 background: linear-gradient(to bottom, white, black);
}

CSS Output

.example {
 display: -webkit-box;
 display: -ms-flexbox;
 display: flex;
 -webkit-transition: all .5s;
 transition: all .5s;
 -webkit-user-select: none;
 -moz-user-select: none;
 -ms-user-select: none;
 user-select: none;
 background: -webkit-linear-gradient(top, white, black);
 background: linear-gradient(to bottom, white, black);
}

cssnext

Here is an example of using the cssnext PostCSS plugin. It transforms CSS specs into more compatible CSS so you don’t need to wait for browser support.

CSS Input

:root { 
  --red: #d33;
}
a {
  &:hover {
    color: color(var(--red) a(54%));
  }
}

CSS Output

a:hover { 
  color: #dd3333;
  color: rgba(221, 51, 51, 0.54);
}

There are hundreds of plugins in every category, from images and fonts, linters, syntaxes, better readability, and much more. We could be here all day if we were to show examples from all of them.

Active Development

The PostCSS project is very active and popular on Github, with a little under 20,000 stars and 1000+ forks.

Github activity (as of Oct, 2018) POSTCSS
# of open issues 12
# of pending pull requests 1
# of total commits 2,726

Summary

As you can see, PostCSS can be a powerful tool when it comes to transforming your CSS using JavaScript. It can either be a replacement for your preprocessor or you could use them together. With its large ecosystem of plugins, it makes it much easier to introduce new code to your development teams.

Have you been using PostCSS yet? If so, let us know below in the comments.

Related Articles

PostCSS – Transforming Your CSS with JavaScript was last modified: October 18th, 2018 by Brian Jackson
Share This