How to use Hugo template variables in SCSS files (in 2018)

Ben Bozzay
Fullstack Digital
Published in
5 min readJul 12, 2018

--

Hugo 0.43 added the ability to execute a resource as a Go template, meaning template variables can now be used to modify stylesheets.

With the addition of Hugo Pipes comes default support for SASS/SCSS. One of the biggest advantages of using SCSS is the ability to define variables that are used throughout your stylesheet and organize styles into partial files.

The addition of resources.ExecuteAsTemplate in 0.43 means that we could, for example, use our config file to define the values for our SCSS variables!

Using Hugo’s variables or params in SCSS files could allow a non-technical user to use a CMS like Forestry.io to easily change styles without any understanding of stylesheets or SASS.

Furthermore, we could significantly reduce the size of our stylesheet by conditionally importing SCSS (more on this in the next tutorial).

As our team wraps up development of Pancakes Builder (an open source builder theme for Hugo), we were thrilled with this particular release. Our original solution for user-defined styles was to inline some styles. Now, we’ve refactored the theme to use template variables to define our SCSS variables.

The theme also contains numerous elements like sliders, accordions, contact forms etc.. However, a user will probably not use all supported elements. Our styles and JS are now conditionally included based on the elements in use.

How to use template variables within SCSS

Refer to my last tutorial on how to use SASS with Hugo in 2018 and Hugo’s new resource functions.

  1. Add template support to your stylesheet

We’ll add template support to main.scss, which imports our partial SCSS.

{{ $styles := resources.Get “scss/main.scss” | resources.ExecuteAsTemplate “style.main.scss” . | 
toCSS |
minify |
fingerprint }}

Note: it does not seem like you can currently use this method with partial SCSS files (such as _variables.scss).

resources.Get creates a new resource object based on a path to a file in the /assets directory. Then, we use resources.ExecuteAsTemplate with the resource type prepended to the name of the file. We add . to pass the context (more on this later). We then chain the toCSS function (to compile our SCSS to CSS), minify (to reduce file size), and fingerprint for cache-busting.

In the code snippet above, resources.Get generates a file in the resources directory:

In this particular example fingerprinting is enabled, which is why this file name seems weird

We can now link to the newly generated resource:

<link rel=”stylesheet” 
href=”{{ $styles.Permalink }}”
integrity=”{{ $styles.Data.Integrity }}”
media=”screen”>

Make sure to use Data.Integrity with fingerprint (here’s why).

2. Add Sass variables to main.scss

Since we can’t use template variables within our partial files, but we can use them within our main.scss file, we simply need to define our variables at the top of main.scss (above any imported files).

3. Create Hugo variables or params

We could use .Params (in our config file), Data files, or even page variables within our stylesheet. It’s best to define site-wide variables in the config file or data files.

  • Using config.toml:

In our config file we add a few params: container_size with a value of 1080px and container_size_wide with a value of 1350px.

Now we include these values in main.scss using .Site.Params:

{{ .Site.Params.container_size | default "1100px" }}

Since we will reference our $container style variable throughout our template, we do not want an empty value.

On the off chance that a user does not set a value for the variable, the default value will be used. It is critical that you have fallbacks for style variables that use template variables/params!

In our _layout.scss file we reference our SCSS variable as normal, but it’s now based on the value for the param in .config.toml!

  • Using a data file and YAML/front matter

Our data file “colors” will be used to set the primary color variable used in our SCSS files.

Using !default in SCSS

Our data file has several fields:

We’ll referenceprimary_color using:

{{ .Site.Data.color.primary_color | default "#7a8288" }}

Now our $primary-color SCSS variable is based on the value for the primary_color variable in our data file!

Limiting potential values and maintaining valid variables

We can use default to provide a fallback for empty values. However, we also need to make sure that only supported values are used.

For example, our color fields require a # if a hex value is used. We don’t want to preprend this to our template variable because the user might decide to use rgba instead.

We can use field types in a CMS like Forestry to control field values based on the field type.

For example, we can use the color picker field to generate a hex code with the # automatically added:

We could also limit supported values using a select drop down field:

What’s next?

The next tutorial will cover how to signficantly reduce CSS and JS file sizes by conditionally including CSS based on the components used on the page. Follow me on Twitter to get notified when the next tutorial is ready!

--

--