Richard Zimerman

@zimrick

How to set up a postcss pipeline with variable sharing in gulp

Create a style pipeline from scratch taking advantage of postcss and future-proof css with cssnext, as well as variable sharing between css and js.

Setting up a basic workflow for postcss with gulp is fairly straightforward. Cssnext also allows us to specify variables in a central javascript file that can be used across your entire codebase. This means that you can standardise styles further, for those cases where styling in both css and javascript is sometimes unavoidable (e.g. data visualization).

I will mainly focus on providing support for variables, custom media queries and partial imports. In order to keep this tutorial reasonably short I can’t cover more than that, but I hope that by the end you will have enough of an overview to be able to add your own plugins to take advantage of more advanced features of postcss.

The source code for this examples can be found on github.

1. Basic setup for gulp

To get started initialise a new folder with npm. In this folder you will need a src and css folder. The src folder will contain the uncompiled css, and the css folder will contain the processed/compiled css files.

$ mkdir postcss-starter-gulp && cd postcss-starter-gulp
$ npm init
...
$ mkdir src css

2. Add gulp dependencies

Next you will have to install gulp and some additional gulp packages. Make sure that they are all listed in package.json.

$ npm install gulp gulp-postcss autoprefixer postcss-cssnext postcss-partial-import --save-dev

3. Add gulpfile

Create a gulpfile.js in the root of your project. Here’s what the file should look like:

// gulpfile.js
var gulp = require("gulp")
var postcss = require("gulp-postcss")
var partialImport = require("postcss-partial-import")
var cssnext = require("postcss-cssnext")
gulp.task("css:build", function() {
var processors = [
partialImport(),
cssnext({
browsers: ["> 1%"],
})
]
return gulp.src("./src/main.css")
.pipe(postcss(processors))
.pipe(gulp.dest("./css"))
})
gulp.task("default", function() {
gulp.watch("./src/**/*.css", ["css:build"])
})

Our gulpfile contains two tasks, one for building the css files, and the default task for watching the src directory for changes. The watcher will run the build command when anything in the src folder changes. The build task will look for a main.css file in the src directory, and will process that file using the processors specified (in this case partialImport and cssnext). Cssnext will transform the css to be compatible with browsers that have more than 1% market share (according to caniuse database). The processed css will be output to the ./css directory.

To run the gulp tasks in our project without installing gulp globally, we need to add some npm scripts to our package.json.

// package.json
...
"scripts": {
"css:watch": "gulp",
"css:build": "gulp css:build",
"test": "echo \"Error: no test specified\" && exit 1"
},
...

Now we can run the gulp tasks using npm, $ npm run css:watch and $ npm run css:build.

4. Add sample css

Create a main.css file in the src directory and add some sample css (as shown below) to check the compilation process.

// ./src/main.css
:root {
--color-blue: #2196F3;
--color-pink: #E91E63;
}
@custom-media --md-viewport (min-width: 62em);
.blue-container {
background: var(--color-blue);
}
@media (--md-viewport) {
.blue-container {
background: var(--color-pink);
}
}

Once you run the gulp task via npm…

$ npm run css:build

…the above css should successfully compile to this:

// ./css/main.css
.blue-container {
background: #2196F3;
}
@media (min-width: 62em) {
.blue-container {
background: #E91E63;
}
}

5. Add js variables and js media queries

To go one step further, we can make the variables color-blue and color-pink available for both css files and javascript files. To do this you will have to create a ./src/styleVariables.js, a ./src/mediaQueries.js, and alter ./src/main.css and gulpfile.js.

To begin with, remove all variable definitions and custom media query definitions from main.css. You should be left with this:

// ./src/main.css
.blue-container {
background: var(--color-blue);
}
@media (--md-viewport) {
.blue-container {
background: var(--color-pink);
}
}

Next, define your variables in a simple javascript object in ./src/styleVariables.js.

// ./src/styleVariables.js
module.exports = {
"color-blue": "#2196F3",
"color-pink": "#E91E63",
}

Then define your media queries also as a simple javascript object in ./src/mediaQueries.js.

// ./src/mediaQueries.js
module.exports = {
"md-viewport": "(min-width: 62em)",
}

Finally, you will have to make the cssnext processor aware of the existence of styleVariables.js and mediaQueries.js. In order to do that you will have to add some code to gulpfile.js. To do this, import the styleVariables.js and mediaQueries.js into your gulpfile and plug them into the cssnext options.

// gulpfile.js
var gulp = require("gulp")
var postcss = require("gulp-postcss")
var partialImport = require("postcss-partial-import")
var cssnext = require("postcss-cssnext")
var styleVariables = require("./src/styleVariables")
var mediaQueries = require("./src/mediaQueries")
gulp.task("css:build", function() {
var processors = [
partialImport(),
cssnext({
browsers: ["> 1%"],
features: {
customProperties: {
variables: styleVariables,
},
customMedia: {
extensions: mediaQueries,
}
}

})
]
return gulp.src("./src/main.css")
.pipe(postcss(processors))
.pipe(gulp.dest("./css"))
})
gulp.task("default", function() {
gulp.watch("./src/**/*.css", ["css:build"])
})

So now you have a simple postcss processor that allows you to share variables between css and js. For other cool stuff that you can add to this setup, check out the postcss github repo.

You can find the code used for this tutorial on github.

Hacker Noon is how hackers start their afternoons. We’re a part of the @AMIfamily. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.
To learn more, read our about page, like/message us on Facebook, or simply, tweet/DM @HackerNoon.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!

More by Richard Zimerman

Topics of interest

More Related Stories