DEV Community

Discussion on: How to add TailwindCSS to your Hugo site

littleninja profile image
Sarah (she/her)

Thanks for this write-up! This is helping me work through Hugo pipes with Tailwind CSS ♥️

Small discrepancy with this note:

  • We also want to pipe it through fingerprint so that the browser does not cache old versions of our stylesheet

From what I've read, integrity is a security feature to make sure static resources haven't been tampered with, e.x. loading a JavaScript library from a cross-origin CDN. This may have cache-busting qualities, I'm not sure. Could you clarify?

littleninja profile image
Sarah (she/her)

Now that I've got Tailwind styles building and rendering (yay! and your article helped 💪🏻), time to purge! The un-optimized stylesheet is 5.95MB 😱. Previous setup made it under 3KB.

(Still working through it, would love to swap notes! Will be starting a new branch on my personal site repo:

divrhino profile image
Div Rhino Author

Cool, thanks for sharing the link to your branch.

Do you have any specific ideas in mind that you'd like swap notes on?

kareemsalah227 profile image
Kareem Salah

Thanks a lot Sarah for raising this, I wouldn't have seen this coming before reading your comment.

I would really appreciate if you have any tips on how to optimise and purge this CSS bundle.

This is my very first day with Hugo and I'm feeling so lost, can't come up with any ideas yet on how to optimise this particular CSS bundle.

Thread Thread
divrhino profile image
Div Rhino Author • Edited

Hello Kareem,

Although you've directed your comment above to Sarah, I thought I'd interject with some tips that may be helpful. Firstly, optimising CSS in this instance probably has more to do with TailwindCSS than with Hugo. So here are just a few things that have helped me:

  1. TailwindCSS allows you to use PurgeCSS to remove styles that aren't being used. Writing purgeable HTML helps the purge process. You can configure PurgeCSS in your tailwind.config.
  2. I often find that I tend to use a custom colour palette in most of the sites I design and build, so I avoid extending the Tailwind colours and just use custom colours in my config, instead
  3. Because flexbox and CSS grid are now pretty well-supported, I don't often find a need for certain things like floats. So being able to remove floats and similar features is very handy.

The tailwind docs have more useful optimisations.

Hope this is a useful starting point. :) 🍍

Thread Thread
littleninja profile image
Sarah (she/her)

This is a useful starting point! To add, the official Hugo docs show how to purge CSS with PostProcess. I was able to optimize my Tailwind styles without modifying the Tailwind config, but Div Rhino's suggestions can help you optimize further.

Here are the steps in code. These details are also in the link above to the Hugo docs:

First, in your config file:

  writeStats = true
Enter fullscreen mode Exit fullscreen mode

Next, in your PostCSS config file:

const purgecss = require('@fullhuman/postcss-purgecss')({
    content: [ './hugo_stats.json' ],
    defaultExtractor: (content) => {
        let els = JSON.parse(content).htmlElements;
        return els.tags.concat(els.classes, els.ids);

module.exports = {
    plugins: [
        ...(process.env.HUGO_ENVIRONMENT === 'production' ? [ purgecss ] : [])
Enter fullscreen mode Exit fullscreen mode

Lastly, in your layout file (layouts/_default/baseOf.html or a style partial):

{{ $css := resources.Get "css/main.css" }}
{{ $css = $css | resources.PostCSS }}
{{ if hugo.IsProduction }}
{{ $css = $css | minify | fingerprint | resources.PostProcess }}
{{ end }}
<link href="{{ $css.RelPermalink }}" rel="stylesheet" />
Enter fullscreen mode Exit fullscreen mode

To walk through what's happening here:

  1. Add configuration writeStats = true. If successful, this will write a hugo_stats.json file at the root of your theme or site.
  2. Add PurgeCSS with a custom extractor to your PostCSS config. The custom extractor will use the class names extracted by the hugo_stats.json and glob patterns to find your layout files to optimize Tailwind styles.
  3. Add a pipe to apply resources.PostProcess in the layout file where you define your styles.
divrhino profile image
Div Rhino Author

Hello Sarah,

Thank you for your comment. Yes, you are correct. The proper role of fingerprint is to ensure the resources have not been tampered with when they are being served.

However, in our case, we assume the assets are all being hosted on the same server, so a simple refresh could ensure we're getting the correct asset (i.e. no middle person intercepting it first).

Cache-busting is a nice side-effect, though. But I do see how the wording in the article makes it look like it is the main function. I will update the content to reflect your point. <3