Codementor Events

Styling a Landing Page with PostCSS

Published Dec 19, 2016Last updated Jan 18, 2017
Styling a Landing Page with PostCSS

Why do we need PostCSS?

We already have Sass, LESS, and Stylus — why do we need another pre-processor like PostCSS?

Sass has a syntax of writing styles which is unique to Sass while PostCSS does not impose any syntax for writing styles — it is more of a tool that transforms CSS. PostCSS relies on a catalog of plugins to do the actual transformation. The plugins are written in JavaScript and the input CSS is converted into a tree which the plugins transform. PostCSS converts the final transformed tree back to CSS.

Back to the original question. Why do we need PostCSS?

PostCSS is faster, modular, and more flexible than other existing pre-processors.

1. Faster than Sass

The PostCSS github page has performance benchmarks. The benchmark results are shown below.

postcss

Clearly, the winner is PostCSS — it is twice as fast as Sass.

2. Modular

The strength of PostCSS is its plugin ecosystem. The PostCSS catalog has several categories of plugins including Color, Fonts, Future, Grids, Images, Media-queries, and Sass. Each category has several plugins within it.

PostCSS converts the initial CSS into an Abstract Syntax Tree (AST), and allows each plugin to do its transformation. When all transformations are complete, it converts the final tree to an output CSS which can be rendered in the browser. Since each plugin does only a small but specific transformation, PostCSS is modular.

3. Flexible

PostCSS is flexible. It does not have any specific syntax by itself. Instead, it supports features available in other pre-processors like Sass. There is a plugin category called Sass. Most of the popular Sass features are supported by these plugins.

  • simple-vars is a plugin that supports Sass-like variables.
  • simple-extend is a plugin that "extends" a CSS class.
  • nested is a plugin that unwraps nested rules.
  • mixins is a plugin that enables mixins.

There is also a less-engine plugin that transforms Less to CSS.

Apart from supporting existing syntaxes, PostCSS allows anybody to author a PostCSS plugin and publish it to the catalog.

Getting started with PostCSS

PostCSS has a command line interface (CLI) which can be installed via NPM.

npm install -g postcss-cli

PostCSS transforms input CSS to the desired output CSS using plugins. Autoprefixer is a popular plugin that adds vendor prefixes to CSS rules. The below input CSS needs to be transformed with vendor prefixes.

p {
  display: flex
}

Install Autoprefixer using NPM.

npm install -g autoprefixer

The command line script to run PostCSS requires the following parameters.

  • --use Specifies a plugin.
  • --output Specifies an output file.
postcss --use autoprefixer --output output.css input.css

The output CSS produced has all the vendor prefixes applied.

p {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex
}

Next, we move on to using PostCSS within our project build. The popular build tools are Webpack, Gulp, and Grunt. For this tutorial, we will learn how to use PostCSS with Webpack.

Build a simple landing page

The landing page that we are going to build is quite simple. It has a header, footer, and content. The content is three blocks floated horizontally. Each block has its own background image. The text within the block is centered. The final landing page is shown below.

postcss

Bootstrap the project with Webpack

We will start by creating a landing page project.

npm init

The npm init command will create a package.json. Add webpack and webpack-dev-server as dependencies.

npm install webpack webpack-dev-server --save-dev

Running the webpack-dev-server command will run a web server which will open the index.html page at http://localhost:8080. The contents of the index.html is given below.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>PostCSS Demo</title>
    <script src="main.js"></script>
  </head>
  <body>
    <div class="header">
      PostCSS Demo
    </div>
    <div class="row">
      <div class="col-fast">
        Fast
      </div>
      <div class="col-modular">
        Modular
      </div>
      <div class="col-flexible">
        Flexible
      </div>
    </div>
    <div class="footer">
      PostCSS is awesome!
    </div>
  </body>
</html>

We will use CSS to style the index page. Add a CSS file main.css as follows.

body {
  font-family: Monaco;
  width: 640px;
  margin: auto;
}

.header {
  padding: 20px;
  font-size: 1.5em;
}

.row {
  padding: 20px;
}

.footer {
  padding: 20px;
  font-size: 0.8em;
  text-align: right;
}

Webpack uses an entry JavaScript file to kick-start the build process. Add index.js which will serve as the entry point of Webpack build.

require("./main.css");

Webpack uses the webpack.config.js file for configuring the build process. Define the Webpack configuration as follows.

module.exports = {
  entry: './index.js',
  output: {
    filename: 'main.js'
  },
  module: {
    loaders: [
      {
        test:   /\.css$/,
        loader: "style-loader!css-loader"
      }
    ]
  }
}

The main.css file that is processed by css-loader module. The output of thecss-loader is processed by another module style-loader. The style-loader embeds the output CSS into the head tag of index.html.

Install the two loaders using npm.

npm install css-loader style-loader --save-dev

On running webpack-dev-server, the landing page can be viewed at http://localhost:8080. The screenshot of the landing page is shown below.

postcss

Using PostCSS to style the page

Sass and Less are popular because we can define variables that can be reused across multiple styles. For our landing page, we can add a background color to the header and footer.

$primaryBackColor: #0047AB;

.header {
  background-color: $primaryBackColor;
}

.footer {
  background-color: $primaryBackColor;
}

We can add a border to the middle section with the same color as $primaryBackColor.

.row {
  border: 2px solid $primaryBackColor;
}

The text color for header and footer can be abstracted to a variable $primaryTextColor as follows.

$primaryTextColor: #FFF;

.header {
  color: $primaryTextColor;
}

.footer {
  color: $primaryTextColor;
}

To make the CSS example above to work, we need to use postcss-loader as a Webpack module. In addition, we need to use postcss-simple-vars plugin.

npm install postcss postcss-loader postcss-simple-vars --save-dev

The Webpack configuration should have the following PostCSS settings.

module.exports = {
  entry: './index.js',
  output: {
    filename: 'main.js'
  },
  module: {
    loaders: [
      {
        test:   /\.css$/,
        loader: "style-loader!css-loader!postcss-loader"
      }
    ]
  },
  postcss: function () {
    return [require('postcss-simple-vars')];
  }
}

After running webpack-dev-server with the new Webpack configuration, we get a better looking landing page.

postcss

Reusing styles

Another plugin that is extremely useful is the postcss-simple-extend plugin. The plugin defines placeholders for repetitive code. The three content blocks have similar CSS elements. The only difference is the background image. The CSS for a single block is as follows.

.col-fast {
  width:180px;
  height:360px;
  font-size: 30px;
  position: relative;
  float: left;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 8px;
}

.col-fast::before {
  content: ' ';
  background-image: url('images/fast.jpg');
  display: block;
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  opacity: 0.3;
  background-repeat: no-repeat;
  background-position: 50% 0;
  background-size: cover;
}

To avoid repetitive code, the postcss-simple-extend can be used. We will install postcss-simple-extend plugin along with a Webpack module url-loader. The url-loader plugin will process the background image.

npm install postcss-simple-extend url-loader --save-dev

The Webpack config for PostCSS needs to be modified as well.

postcss: function () {
  return [
    require('postcss-simple-vars'),
    require('postcss-simple-extend')
  ];
}

The postcss-simple-extend plugin has a define placeholder. We will define two placeholders for the block (col) and the background image (col-before).

@define-placeholder col {
  width:180px;
  height:360px;
  font-size: 30px;
  position: relative;
  float: left;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 8px;
}

@define-placeholder col-before {
  content: ' ';
  display: block;
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  opacity: 0.3;
  background-repeat: no-repeat;
  background-position: 50% 0;
  background-size: cover;
}

The placeholders can be used in multiple places by using @extend statement.

.col-fast {
  @extend col;
}

.col-fast::before {
  @extend col-before;
  background-image: url('images/fast.jpg');
}

.col-modular {
  @extend col;
}

.col-modular::before {
  @extend col-before;
  background-image: url('images/modular.jpg');
}

.col-flexible {
  @extend col;
}

.col-flexible::before {
  @extend col-before;
  background-image: url('images/flexible.jpg');
}

Nesting styles

There are three block elements which are floated to the left of each other. If the float is not cleared, the landing page won't look pretty. The :after psuedo-element can be used to clear the float.

.row {
  padding: 20px;
  border: 2px solid $primaryBackColor;
  background-color: $contentBackColor;

  &::after {
    content: ".";
    visibility: hidden;
    display: block;
    height: 0;
    clear: both;
  }
}

To use nested styles in your CSS, add the postcss-nested plugin to the webpack config.

npm install postcss-nested --save-dev

The plugin should be included in the Webpack config.

postcss: function () {
  return [
    require('postcss-simple-vars'),
    require('postcss-nested'),
    require('postcss-simple-extend'),
  ];
}

The floating blocks can also be nested as follows.

.col-fast {
  @extend col;

  &::before {
    @extend col-before;
    background-image: url('images/fast.jpg');
  }
}

Summary

PostCSS does not have a syntax by itself. It allows various plugins to be included in the build process. Each plugin supports an extended CSS syntax. The autoprefixer plugin adds vendor prefixes to CSS. The postcss-simple-vars plugin allows reuse of CSS rules. The postcss-simple-extend allows reuse of CSS blocks. The postcss-nested plugin allows nested CSS styles. There are around 200 plugins in the PostCSS ecosystem. It is easy to author your own plugin.

There is an accompanying github project for the tutorial. You can also check out other tutorials related to this topic like: Compiling SASS and PostCSS with Angular CLI, and Building a flipper using React JS and LESS CSS.

Discover and read more posts from Vijay Thirugnanam
get started
post comments1Reply
Danjavia
8 years ago

Nice article!. It’s posible to communicate with your for learning about reactjs e2e tests and UT?