Combine SASS/SCSS and CSS in a bundle

Hi

The theme I’m using uses a Partial to make use of Site.Params to set the colours in CSS variables.
Although this does work fine, I’m not really fan of this cluttering of my site’s <head>.

That’s why I was thinking of using SASS/SCSS variables, based on Initialize Sass variables from Hugo templates and hugo-testing/layouts/partials/get-scss-vars.html at hugo-github-issue-10558 · jmooring/hugo-testing · GitHub.

The transpiled CSS should then be included in the bundle together with the rest of the CSS files.

However, I just can’t wrap my head around it.

My setup looks as follows:


assets/scss/
├── _vars.scss
└── main.scss

layouts/partials/head
└── get-scss-vars.html
└── stylesheets.html

/* assets/scss/main.scss */

@import "vars";

/* assets/scss/_vars.scss */

@use "hugo:vars" as h;

body {
    --sidebar-bg-color: h.$sidebar_bg_color;
    --sidebar-img-border-color: h.$sidebar_img_border_color;
    --sidebar-p-color: h.$sidebar_p_color;
    --sidebar-h1-color: h.$sidebar_h1_color;
    --sidebar-a-color: h.$sidebar_a_color;
    /* ... */
    --moon-sun-color: h.$moon_sun_color;
    --moon-sun-background-color: h.$moon_sun_background_color;
};

# layouts/partials/head/get-scss-vars.html

{{ $vars := dict
    "sidebar_bg_color"                  (or .Site.Params.sidebar_bg_color "#202020")
    "sidebar_img_border_color"          (or .Site.Params.sidebar_img_border_color "#515151")
    "sidebar_p_color"                   (or .Site.Params.sidebar_p_color "#909090")
    "sidebar_h1_color"                  (or .Site.Params.sidebar_h1_color "#FFF")
    "sidebar_a_color"                   (or .Site.Params.sidebar_a_color "#FFF")
    # ...
    "moon_sun_color"                    (or .Site.Params.moon_sun_color "#FFF")
    "moon_sun_background_color"         (or .Site.Params.moon_sun_background_color "#515151")
}}

{{ return $vars }}

# layouts/partials/head/stylesheets.html

{{ $bundle := slice }}

{{ $opts := dict
  "targetPath"  "css/vars.css"
  "transpiler"  "dartsass"
  "vars"        (partialCached "head/get-scss-vars.html" .)
}}
{{ with resources.Get "scss/main.scss" | toCSS $opts }}
  {{ $bundle = $bundle | append (slice "{{ .RelPermalink }}") }}
{{ end }}

{{ $bundle = $bundle | append (slice
    (resources.Get "css/poole.css")
    (resources.Get "css/codeblock.css")
    (resources.Get "css/hyde.css")
    (resources.Get "css/poison.css")
    (resources.Get "css/fonts.css")
    (resources.Get "css/lib/katex.css")
    (resources.Get "css/tabs.css")
    (resources.Get "css/custom.css")
  )
}}

{{ $css_bundle := $bundle | resources.Concat "css/bundle.css" | minify | fingerprint }}

<link type="text/css" rel="stylesheet" href="{{ $css_bundle.RelPermalink }}" integrity="{{ $css_bundle.Data.Integrity }}" crossorigin="anonymous">

What is your question?

I would like to figure out how I can combine the transpiled SCSS>CSS in the same bundle as the rest of the CSS.

My current setup results in the error:
execute of template failed: template: partials/head/stylesheets.html:24:37: executing "partials/head/stylesheets.html" at <resources.Concat>: error calling Concat: expected slice of Resource objects, received []interface {} instead

Other attempts resulted in the following error:
error calling toCSS: runtime error: invalid memory address or nil pointer

You are appending a string, not the resource itself. Here’s a simple example of transpiling a Sass file and then appending the CSS files.

assets/
├── css/
│   ├── 01-typography.css
│   └── 02-components.css
└── sass/
    └── main.scss
{{ with resources.Get "sass/main.scss" }}
  {{ $opts := dict
    "transpiler" "dartsass"
  }}
  {{ with . | toCSS $opts }}
    {{ with slice . | append (resources.Match "css/*") | resources.Concat "css/styles.css" }}
      {{ if hugo.IsProduction }}
        {{ with . | minify | fingerprint }}
          <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
        {{ end }}
      {{ else }}
        <link rel="stylesheet" href="{{ .RelPermalink }}">
      {{ end }}
    {{ end }}
  {{ end }}
{{ end }}

Notes:

  • If you can prefix the CSS file names as shown in the file structure above, they’ll be appended in numerical order. That makes it really easy to append all of the CSS files, in the desired order, with the resources.Match function
  • There’s no need set the target path in the transpiler options map. The target path is defined in the call to resources.Concat.
1 Like

I’ll give this a shot tomorrow.

Thanks a lot!
Blazingly fast response :slight_smile: