PostCSS - Transforming Your CSS with JavaScript

By Brian Jackson
Published on October 18, 2018
PostCSS - Transforming Your CSS with JavaScript

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 style sheets 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 among developers over the past 12 months. You can see below that on npm the number of downloads per day has steadily increased. And in total, there have been 21,757,724 downloads between Dec 31 2014 and Jun 28 2016.

And if we take a look at Google Trends for "PostCSS" it appears there is definitely an upwards curve.

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 verses 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. But probably one of the biggest advantages is the use of the plugin ecosystem that accompanies it with more than 200 plugins.

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 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 over 10,000 stars and 500+ forks.

GitHub activityPostCSS
# of open issues20
# of pending pull requests2
# of commits in the last 30 days58

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.

  • Share

Supercharge your content delivery 🚀

Try KeyCDN with a free 14 day trial, no credit card required.

Get started

Comments

Comment policy: Comments are welcomed and encouraged. However, all comments are manually moderated and those deemed to be spam or solely promotional in nature will be deleted.
  • **bold**
  • `code`
  • ```block```
KeyCDN uses cookies to make its website easier to use. Learn more