Using Hugo with PostCSS and PurgeCSS allows you to automatically remove unused CSS and bundle all your styles into a single minified file for production, improving page load times and performance.
Stripping out unused CSS is particularly useful if you use frameworks like Bootstrap as you generally don’t use the entire framework.
You can install the PostCSS and PurgeCSS tools using npm, if you don’t have npm installed you can follow the instructions below for popular Linux distributions.
Installing Node.js and npm
Below are instructions for installing on Arch Linux, Ubuntu, and Fedora.
Arch Linux
sudo pacman -Syu nodejs npm
Ubuntu / Debian
sudo apt update
sudo apt install nodejs npm -y
Fedora
sudo dnf install nodejs npm -y
You can verify the installation with:
node --version
npm --version
You can then go to your Hugo root directory and run:
npm init
npm install postcss postcss-cli purgecss autoprefixer
Setup the postcss.config.js configuration file
From inside the Hugo root directory create the config file postcss.config.js
const { PurgeCSS } = require('purgecss');
const purgeCSSPlugin = () => {
return {
postcssPlugin: 'postcss-purgecss-modern',
Once: async (root, { result }) => {
if (process.env.HUGO_ENVIRONMENT !== 'production') return;
const purgeCSSResult = await new PurgeCSS().purge({
content: [
'./layouts/**/*.html',
'./content/**/*.md',
'./assets/js/**/*.js',
'./hugo_stats.json',
// All themes' layouts and JS
'./themes/**/layouts/**/*.html',
'./themes/**/content/**/*.md',
'./themes/**/assets/js/**/*.js'
],
css: [{ raw: root.toString() }],
defaultExtractor: content =>
content.match(/[\w-/:.]+(?<!:)/g) || [],
});
if (purgeCSSResult.length > 0 && purgeCSSResult[0].css) {
// Replace the entire CSS with the purged version
root.removeAll();
root.append(require('postcss').parse(purgeCSSResult[0].css));
}
},
};
};
purgeCSSPlugin.postcss = true;
module.exports = {
plugins: [
require('autoprefixer'),
purgeCSSPlugin(),
],
};
Add required settings to your hugo.toml configuration file
Then you need to add the following into your hugo.toml config file.
[markup.postCSS]
use = ["postcss"]
[build]
writeStats = true
The writeStats setting is needed so PurgeCSS knows what CSS is being used.
Create css.html partial file to process the CSS files
The file to edit or create next will depend on if you are using a theme or if you are overriding the themes baseof.html in your Hugo project.
In this post I’m going to do the editing from the point of view that you have your own custom theme. If you are overriding a third-party theme then you can edit the files in you hugo project layouts directory instead.
themes/theme-name
├── layouts
│ ├── _partials
│ │ ├── footer.html
│ │ ├── head
│ │ │ ├── css.html
│ │ │ ├── js.html
│ │ │ └── seo.html
│ │ ├── head.html
│ │ ├── header.html
│ │ └── terms.html
│ ├── baseof.html
│ ├── home.html
│ ├── page.html
│ ├── section.html
│ ├── taxonomy.html
│ └── term.html
The above listing is a stripped down version showing some of the essential theme files for a Hugo website.
This website example has a layouts/_partials/head/css.html file that is included as a partial for including all CSS related content.
{{ $cssFiles := slice }}
{{/* Add main.css */}}
{{ $mainCSS := resources.Get "css/main.css" }}
{{ $cssFiles = $cssFiles | append ($mainCSS | postCSS) }}
{{/* Add styles.scss */}}
{{ $stylesSCSS := resources.Get "scss/styles.scss" | toCSS | postCSS }}
{{ $cssFiles = $cssFiles | append $stylesSCSS }}
{{/* Add fonts.scss */}}
{{ $fontsSCSS := resources.Get "scss/fonts.scss" | toCSS | postCSS }}
{{ $cssFiles = $cssFiles | append $fontsSCSS }}
{{ if hugo.IsDevelopment }}
{{ range $cssFiles }}
<link rel="stylesheet" href="{{ .RelPermalink }}">
{{ end }}
{{ else }}
{{ $bundle := $cssFiles | resources.Concat "css/styles-bundle.min.css" | minify | fingerprint }}
<link rel="preload" href="{{ $bundle.RelPermalink }}" as="style" integrity="{{ $bundle.Data.Integrity }}" crossorigin="anonymous">
<link rel="stylesheet" href="{{ $bundle.RelPermalink }}" integrity="{{ $bundle.Data.Integrity }}" crossorigin="anonymous">
{{ end }}
NOTE: Only files in the assets directory are processed by Hugo. If you have these files in the static directory they need to be moved to assets.
The file above will process the CSS files with PostCSS stripping out any unused CSS then if it is a development build it will create multiple CSS files without minifying them. If it is not a development build then it combines all the CSS files into styles-bundle.min.css then minifies it.
Include the css.html file in your Hugo website
So now you need to make sure that your Hugo setup includes this css.html file somewhere in the head tag in the html of your website by using:
{{ partial "head/css.html" . }}
Test your Hugo website to make sure everything is working correctly
Once you have done this have a look at the page source in both development builds and production builds:
Development build:
rm -Rf public && hugo server
Test production build:
rm -Rf public && hugo && cd public && php -S localhost:1313
Minified production build:
rm -Rf public && hugo --minify && cd public && php -S localhost:1313
In the above examples I’m using php to easily spin up a webserver to test the production builds. If you don’t have php installed then you can either install php or use another tool to test the production builds before you deploy them.
Conclusion
If you setup everything correctly you should be stripping unused css from your css files and have a minified styles-bundle.min.css file in your production builds which will help improve performance when loading your website.
Tags:
Latest Blog Posts:
How to Setup Hugo Admonitions (Markdown Callouts in Hugo)
By adding Hugo Admonitions to your website so you can easily add stylish note bars for things like tips, warnings, cautions, important information etc. You can do this quickly and easily directly using markdown.
How to setup Syntax Highlighting with Copy Button using Hugo
In this post, I’ll show you how to add syntax highlighting and a ‘Copy’ button to your Hugo code blocks using a single self-contained JavaScript file. You’ll be able to highlight code in multiple languages, optionally show line numbers, and let users copy snippets with one click.
How to strip unused CSS from your CSS files and Minify them into a single CSS file using Hugo
Using Hugo with PostCSS and PurgeCSS allows you to automatically remove unused CSS and bundle all your styles into a single minified file for production, improving page load times and performance.
Make an application always load as a floating window in Cosmic Desktop
Make an application always load as a floating window in Cosmic Desktop
Why I migrated from Wordpress to Hugo
My reasons for migrating from Wordpress to the Hugo static website generator
Using Gtk4 With C# and Gir.Core Box Layout Tutorial
In this box layout tutorial, you will learn how to build a C# Gtk Application that makes use of the box layout to display multiple widgets both vertically and horizontally. You will also learn how to use a box layout to display an icon and a label inside a Gtk.Button widget.
Using Gtk4 With C# and Gir.Core Hello World Tutorial
In this hello world tutorial you will learn how to build a basic C# Gtk Application with a single Gtk Button widget inside it
Fix Unity Game Engine Crashing With Nvidia Graphics Card
A couple of years ago I was having issues with the Unity Editor randomly crashing on me. I tried many thing such as
prime-run
etc without success.I found through trial and error from multiple forum posts that launching Unity Hub with the following worked well for me and stoped the random crashing issues.
I am posting this just in case I need it again and hopefully others will find it helpful.
Adventure Game Studio AGS MacOS Build
How to play windows AGS games in a MacOS AGS Bundle and how to release your own games in a MacOS AGS Bundle with codesigning and notorization