Adding PostCSS to a Hugo Static Site

Last updated on May 16, 2020

PostCSS is a fantastic tool to add to your website. It helps to do some post-processing magic for your CSS files with its plugin ecosystem. Some notable plugins that I personally like a lot are autoprefixer, a plugin that adds vendor prefixes to your CSS, and TailwindCSS, a utility-based CSS framework.

However, when I was adding PostCSS to my Hugo websites, it wasn't as straight-forward as reading the documentation and following the instructions. Nope, not at all. Just have a look at the PostCSS pipe function documentation in on the Hugo documentation site. It's terribly sparse with hardly any valuable examples.

I spent a good few hours just trying to get it to work. So, for the benefit of those who find this while trying to figure out the Hugo documentation, here's the full steps.

Of course, the pre-requisites required is having Hugo installed. I'm also going to assume that you have the npm installed.

Step 1: Install the Dependencies

Run the following (assuming you want to use autoprefixer):

$ npm install postcss-cli autoprefixer

This will install the PostCSS cli to your node_modules.

Step 2: Create the PostCSS Configuration File

In the root folder, create the postcss.config.js file.

In this example, we are only configuring autoprefixer, however you should go ahead and configure the rest of the plugins that you are installing as well.

# In the /postcss.config.js file
# Of course, add in the actual browser range that you want to target. 
# This is just an example

module.exports = {
  plugins: [
      overrideBrowserslist: ["> 0.5% in US", "Safari > 9"]

Step 3: Create Your CSS File

Create a main.css file in your configured assets folder. By default, in Hugo, it is the /assets folder. This assets folder is special to Hugo, as Hugo searches within this folder for asset files to ingest and process. This is not the same as the static folder, which Hugo does not touch.

In this example, type the following in /assets/css/main.css:

p {
  font-size: 20px

Step 4: Tell Hugo to Generate the Styles

Now we come to the Hugo-specific part. In your baseof.html layout file, include the following in the <head> portion of the html template:

    {{ $style := resources.Get "css/main.css" | resources.PostCSS  (dict "config" "./postcss.config.js") | resources.Minify | resources.Fingerprint "sha512"  }}
    <link rel="stylesheet" href="{{ $style.RelPermalink }}" integrity="{{ $style.Data.Integrity }}"> 

As Hugo templating has a terrible readability level, the step-by-step walkthrough of what this does is:

  • resources.Get "css/main.css: In the assets directory, look for the main.cssfile in the css sub-directory. The pipe passes this file pointer to the next function.
  • resources.PostCSS (dict "config" "./postcss.config.js"): Use the PostCSS configuration file (that we had created) as the configuration to process the CSS file.
  • resources.Minify: Minify the processed CSS file.
  • resources.Fingerprint "sha512": For the generated file, create a cryptographic hash to allow the browser to check for the integrity of the fetched resource. Refer to Mozilla's article on subresource integrity for more details.

This minfied file output is assigned to the $style variable (:= is the variable assignment operator in Go). We then use the relative permalink and the integrity hash to create the <link> element.

Yay! Now you have PostCSS hooked up to your Hugo website!