3 minutes
Written: 2023-06-17 17:29 +0000
Dart Sass and Hugo Themes
Quick notes on variables,
dart-sassandhugo
Background
Recently I decided that it was annoying for me as a user to not know which links on my site were internal and which led off to an external site.

Figure 1: The desired end-result, blue for internal links, purple for external links, colors chosen with ColorHexa
However, since hugo requires baseurl for generating meaningful rss and
sitemap files, this meant either hardcoding the variable into my theme, or
figuring out how to pass variables from my config.toml to my theme’s
(generated) css.
This about the latter, and is heavily based off of this post on the Hugo Discourse.
The CSS
The crux of the implementation is simply the use of attribute selectors:
1a {
2 &[href^="/"],
3 &[href*="rgoswami.me"],
4 &[href^="#"] {
5 border-bottom: #0380ff 0.125em solid;
6 }
7 &:not([href^="/"]):not([href*="rgoswami.me"]):not([href^="#"]) {
8 border-bottom: #9b36ff 0.125em solid;
9 }
10}
Where the main sticking point is being able to pass the name of the site from
the configuration. Although this could be done with libsass and hugo as
detailed in the discourse post, it is conceptually clunky, since partials are
not respected when using ExecuteAsTemplate with hugo-pipes. A better SCSS
processor could probably take in a better configuration option object…. Which
leads to the next section.
Dart Sass
At some point which I didn’t have time to figure out, libsass got phased out
in favor of Dart Sass and includes (among other features) a nifty math
module. This had a few side effects:
- I could swap my hand-kanged
expfunction formath.exp()and also had to transition to usingcalc()more (as in 3938ac2). - I could pass variables from
hugotoscssand from there tocssfor attribute selectors (as in 804d417)
CI Updates
For various reasons, hugo (even the extended version) does not seem to include
dart-sass-embedded though the snap package does (as noted here on Discourse).
1- name: Setup Hugo
2 uses: peaceiris/actions-hugo@v2
3 with:
4 hugo-version: '0.111.3'
5 extended: true
6- name: Install Dart Sass Embedded
7 run: sudo snap install dart-sass-embedded
Local Usage
hugo serve will correctly compile and load the theme if hugo env recognizes the dart-sass-embedded installation:
1$ hugo env
2hugo v0.112.3+extended linux/amd64 BuildDate=unknown
3GOOS="linux"
4GOARCH="amd64"
5GOVERSION="go1.20.4"
6github.com/sass/libsass="3.6.5"
7github.com/webmproject/libwebp="v1.2.4"
8github.com/sass/dart-sass-embedded/protocol="1.2.0"
9github.com/sass/dart-sass-embedded/compiler="1.54.8"
10github.com/sass/dart-sass-embedded/implementation="1.54.8"
dart-sass-embedded is a node package, which means that npm can be used:
1DART_SASS_VERSION=1.54.8 npm install sass-embedded-linux-x64@${DART_SASS_VERSION}
2PATH=$PATH:./node_modules/sass-embedded-linux-x64/dart-sass-embedded/ hugo env
Personally I ended up using micromamba to grab dart-sass as well.
Passing Variables
User Perspective
The theme users simply updates their configuration to include the relevant variables:
1baseurl = "https://rgoswami.me/"
2[params.style]
3site_url = "rgoswami.me" # Same as baseurl
Theme Dev Perspective
With the hugo asset processing pipeline for dart-sass, the relevant options need to be (minimally) set:
1{{ $options := (dict "targetPath" "main.css" "transpiler" "dartsass" "vars" site.Params.style) }}
2{{ $style := resources.Get "scss/main.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint }}
3<link rel="stylesheet" href="{{ $style.RelPermalink }}">
Where vars takes a section corresponding to the user-defined section (style
in this case). Usage within scss partials looks like:
1@use "hugo:vars" as h;
2$site-url: h.$site_url;
3$link-color: #0380ff;
4$external-link-color: #9b36ff;
Which can finally be used to elegantly setup attribute selector based colors:
1a {
2 &[href^="/"],
3 &[href*="#{$site-url}"],
4 &[href^="#"] {
5 border-bottom: $link-color 0.125em solid;
6 }
7 &:not([href^="/"]):not([href*="#{$site-url}"]):not([href^="#"]) {
8 border-bottom: $external-link-color 0.125em solid;
9 }
10}
Conclusions
Of the many maintenance burdens I have accrued over the years, one of the least often discussed is the underlying theme used for the site. Some day that will be rectified. I think web design via vanilla JS, S(CSS) and HTML is a pretty nifty gateway into other languages (interpreted and compiled). The approach could be (and perhaps should be) extended to color other links and sites differently (e.g. all my content on other sites in blue). For now this works well enough at any rate.
