Converting CSS OutputFormat to Hugo Pipes

I had hugo building a data driven page with a configurable number of repeating elements. Since each element would be styled differently or shown/hidden, I needed CSS rules for each. While solvable via javascript (and even partially with nth-child or nth-of-type selectors), I try to minimize JS as much as possible for pure CSS.

Enter hugo Output Formats. It was straightforward use hugo to generate the css rules for a range of columns and output a new css file.

Detailed setup for custom CSS output
  1. In your content file front matter, simply add an output format parameter. ex: _index.html:
  - html
  - css
  1. Create an index.css file in your layouts/ directory, using standard template rules to dynamically generate the css you want.
  2. I customized the default css media format in the site’s config to change the generated name and output directory:
		path = "/css/"
		baseName = "custom"
  1. Add the generated file to your head.html template:
{{- with  .OutputFormats.Get "css" }}
	<link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .RelPermalink | safeURL }}">
{{ end -}}

This works great, and was the perfect use case for output formats.

I was finishing up my site and adding the production touches with some minimizing and fingerprinting when I realized I couldn’t use Hugo Pipes with this generated css file. While not large, or frequently changing, it seemed better to be able to handle all the css files consistently (and fingerprinting is always good).

Hugo Pipes ExecuteAsTemplate fixes this. To convert, it’s just a few steps:

  1. Move the index.css (or whatever your template was called) file from layouts/ to assets/templates/custom-template.css.
  2. Change the head.html template where you were linking to the generated file:
{{- $customCSS := resources.Get "templates/custom.css" -}}
{{- $customPiped := $compareCSS | resources.ExecuteAsTemplate "css/custom.css" . | minify | fingerprint -}}
<link rel="stylesheet" type="text/css" href="{{ $compareCSS.RelPermalink }}">

Done! Now you have all the benefits of Pipes and still have autogenerated CSS rules.

A few notes:

  • The resource can be stored in any directory structure inside assets that you want, here I’ve used templates/.
    The docs show a SCSS hugo template stored in the scss/ directory. I think it’s better long term to separate plain scss or css files from ones that are hugo templates so there is no confusion or mistakes.
  • if you don’t need them any more, remember to clean up the settings for the custom CSS output format.