Header image

Upgrade Your Hugo Site to Tailwind 4

March 31, 2025

There is a new mayor verison of the popular css utility framework tailwindcss that includes several changes. Here will learn how to update an Hugo site that uses tailwindcss v3 to latest and optimize the build process

Important

  • Do a full backup of your preject or create a new branch to prevent any issues with your actual styles config
  1. Upgrade tailwind package:

    We’ll start using the tailwind upgrado tool from a tailwind v3 project

    npx @tailwindcss/upgrade
    

    This will update the package.json to use latest tailwindcss v4 and also change your main css file to use latest import config

    If there is a line in your css that imports the tailwind.config.js I recommend that you to remove it and modify it and adapt to latest config format

  2. Change hugo pipes

    Now we need to change how hugo pipes will create the css file. I was using postcss pipes with tailwind v3 but we can use @tailwindcss/cli package and and the new css.tailwind hugo pipe

    2.1. First install the latest tailwindcss cli

    npm install -D @tailwindcss/cli
    

    In your layouts/partials folder, create a new css.html file with the following config

    {{ with (templates.Defer (dict "key" "global")) }} {{ with resources.Get"css/styles.css" }} {{ $opts := dict "minify" hugo.IsProduction "inlineImports" true }} {{ with . | css.TailwindCSS $opts }} {{ if hugo.IsProduction }} {{ with . | fingerprint }}
    <link
      rel="stylesheet"
      href="{{ .RelPermalink }}"
      integrity="{{ .Data.Integrity }}"
      crossorigin="anonymous"
    />
    {{ end }} {{ else }}
    <link rel="stylesheet" href="{{ .RelPermalink }}" />
    {{ end }} {{ end }} {{ end }} {{ end }}
    

    2.2. Update your css. Change the css/styles.css filename to point to your css in your assest folder. Now you can use this new partial in your head tag

    <head>
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <meta author="Author Name" />
     <meta name="description" content="{{ .Description " }}">
     <title>{{ .Site.Title }}</title>
    
     {{ partial "head/css.html" . }}
    </head>
    
  3. Hugo Config

    In your hugo config add/replece this build and module config

    [build]
      [build.buildStats]
        enable = true
      [[build.cachebusters]]
        source = 'assets/notwatching/hugo_stats\.json'
        target = 'css'
      [[build.cachebusters]]
        source = '(postcss|tailwind)\.config\.js'
        target = 'css'
    [module]
      [[module.mounts]]
        source = 'assets'
        target = 'assets'
      [[module.mounts]]
        disableWatch = true
        source = 'hugo_stats.json'
        target = 'assets/notwatching/hugo_stats.json'
    
  4. If you are using any plugins for example tailwind typography or daisyui update them to latest version and update your css file

@plugin "@tailwindcss/typography";
  1. Conclusion

Now you are free to build your hugo site again, Check the console output for errors, but if the process ended ok you can safely remove the postcss and autoprefixer packages here is how your css file look like after the update

@import "tailwindcss";

@source 'hugo_stats.json';

@plugin "daisyui" {
 themes:
     light --default,
     dracula --prefersdark;
}

@plugin "@tailwindcss/typography";

@theme {
  --font-ubuntu: ubuntu-regular;
}

@layer base {
  *,
  ::after,
  ::before,
  ::backdrop,
  ::file-selector-button {
      border-color: var(--color-gray-200, currentColor);
  }
}

Comments