Sass and CSS Updates for Hugo

06 May 2026

Sass

I previously wrote about using Sass in my Hugo site here: Sass in Hugo. That example used LibSass, but as noted here, LibSass was deprecated by the Hugo team a few years ago, so I switched to Dart Sass.

I had already downloaded and installed Hugo manually for my Windows machine here:

C:\Program Files\Hugo\hugo.exe

For Dart Sass, I manually downloaded the latest Dart Sass executables from here:

https://github.com/sass/dart-sass/releases

I unzipped the download file and then placed the dart.exe and sass.snapshot files in a new src directory here:

C:\Program Files\Hugo\src

I also copied the provided sass.bat file to the C:\Program Files\Hugo\ directory.

(You can check the Dart version using dart --version at the commmand line.)

Finally I changed my Hugo code to use Dart Sass:

Before:

1
"transpiler" "libsass"

After:

1
"transpiler" "dartsass"

CSS

A recent version of Hugo (v0.158.0) provides access to a more powerful CSS preprocessor: css.Build.

To use this, I upgraded my Hugo installation and then changed my Hugo code accordingly:

Before:

Go Template
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{{ with resources.Get "scss/demo.scss" }}
  {{ $opts := dict "transpiler" "dartsass"
                   "outputStyle" "expanded"
                   "targetPath" "css/demo.css" }}
  {{ with . | toCSS $opts }}
    {{ if hugo.IsDevelopment }}
      <link rel="stylesheet" href="{{ .RelPermalink }}">
    {{ else }}  
      {{ with . | minify | fingerprint }}
        <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
      {{ end }}
    {{ end }}
  {{ end }}
{{ end }}

After:

Go Template
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{{ with resources.Get "scss/demo.scss" }}
  {{ $sass_opts := dict "transpiler" "dartsass"
                         "outputStyle" "expanded"
  }}
  {{ $css_opts := dict
    "externals" (slice "/fonts/*" "/css/*")
    "minify" (cond hugo.IsDevelopment false true)
    "sourceMap" (cond hugo.IsDevelopment "linked" "none")
    "target" (slice "chrome115" "edge115" "firefox116" "ios16.4" "opera101" "safari16.4")
    "targetPath" "/css/demo.css"
  }}
  {{ with . | toCSS $sass_opts | css.Build $css_opts }}
    {{ if hugo.IsDevelopment }}
      <link rel="stylesheet" href="{{ .RelPermalink }}">
    {{ else }}
      {{ with . | fingerprint }}
        <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
      {{ end }}
    {{ end }}
  {{ end }}
{{ end }}

In the modified code, I now have two sets of options:

  • sass_opts for the Dart Sass transpiler.
  • css_opts for the new css.Build function.

I pipe the SCSS resource file through the SASS transpiler and then into the CSS builder:

1
{{ with . | toCSS $sass_opts | css.Build $css_opts }}

In my case I use "externals" (slice "/fonts/*" "/css/*") because my CSS refers to various URLs which I want the CSS builder to ignore. For example:

CSS
1
2
3
4
@font-face {
    font-family: "OpenSans";
    src: url(/fonts/Open_Sans/OpenSans-VariableFont_wdth,wght.ttf);
}

This ensures the targeted file references are passed through from my SASS file to the final CSS file unchanged. Without this, the CSS builder would throw errors about not being able to locate (and therefore process) the above font file.