Hype that needed some time to happen

I bet that when you think about PostCSS you must think something like…

Yet the truth is that PostCSS is around for almost as long as React!

Why PostCSS?

The widest spread application of PostCSS usage is through seamless integration of Autoprefixer (Just one of many PostCSS plugins. Not lib on its own.)

display: flex; // becomes display: -webkit-box;

display: -webkit-flex;

display: -ms-flexbox;

display: flex;

Writing such logic outside of more traditional SASS / LESS mixins and automatically making it part of your app build is just genius.

This sure seems awesome and is the main reason why this particular plugin has 11,103,982 downloads per month on NPM.

It’s obvious that industry needs a concept which PostCSS introduced.

The single PostCSS plugin has more downloads than the most popular JavaScript frameworks / libraries… Check it out on NPM trends.

PostCSS is not coupled with any specific framework / library. It’s a Front-End tool.

Babel for CSS

With plugins or better say set of plugins PostCSS can be used in the same way we use Babel in JavaScript.

CSSnext is set of plugins which among other awesome stuff can transform CSS custom properties into what browsers can interpret today.

Alternative to CSSnext (possibly better maintained) is postcss-preset-env…

:root {

--fontSize: 1rem;

}



h1 {

font-size: var(--fontSize);

}

This will obviously fail to work in most browsers but with PostCSS it will be transformed into.

h1 {

font-size: 1rem;

}

PostCSS is “just” a parser for CSS. This means that with its API one can do anything possible.

Stylelint is PostCSS based! Check this awesome CSS linter here.

How PostCSS?

Weirdly enough the PostCSS is not about the CSS it’s about what JavaScript can do with your CSS.

With that being said, let’s do a simple transform of single display: flex to multiple browser-specific definitions.

// require the postcss for our plugin to work

const postcss = require('postcss'); // export the plugin

module.exports = postcss.plugin('postcss-flex', (opts) => {

opts = opts || {}; return (css) => {

// define the new values

const values = [

'-webkit-box',

'-webkit-flex',

'-ms-flexbox',

]; // iterate through declarations

css.walkDecls('display', decl => {

// ignore everything else other than flex

if (decl.value !== 'flex') return; // map values to actual string

const newDecls = values.map((value) => {

return ` display: ${value}`;

}).join(';'); // add new declarations before the current

decl.before(newDecls);

});

};

});

Essentially PostCSS takes your CSS (or SASS / LESS) source as input, gives you the possibility to alter it and outputs the end result. Simple as that.

For more details regarding PostCSS API please go here. But beware that docs are automatically generated from JSdoc (If anyone ever ask you why you should use JSdocs, just show him/her PostCSS API docs). Even though they are insightful, IMHO it would be better if they were written manually.

Theming

If your theme support requires different palette set for each theme. Together with possibly some other variables which needs to be adjusted eg. font-sizes or border-radius or … One of the easiest (possibly best) ways to achieve this would be to separate mapping of the variables eg. colors, border-radius … in the theme files.

For this scenario, we can @import just the default theme file and replace the import to theme specific file during the build, via PostCSS. As result of this, we can build theme specific CSS bundles easily and never put any references to it in our SASS codebase.

@import './variables'; .button--color-primary {

background-color: $primary;

}

Where variables.scss have such mapping.

@import '~styles/colors/colors'; $primary: $green;

Theme specific variables.blue.scss have different mapping.

@import '~styles/colors/colors'; $primary: $blue;

SASS itself does not support dynamic imports (imports with variables in their path). Issue #279 on Github of SASS

So doing this is practically not possible if you use SASS. At least without PostCSS…

This small plugin is just one example of creative usage of PostCSS.

How does it work?

/*

example of options

const opts = {

originalValue: './variables',

targetValue: './variables.blue'

};

*/ css.walkAtRules((node) => {

const isImport = (node.name === 'import');

const isOriginalValue = node.params.includes(opts.originalValue);



if (isImport && isOriginalValue) {

node.params = `"${opts.targetValue}";`;

}

});

Fun fact

Autoprefixer will eventually become obsolete…