Quick refresher
- Page resources: This is content located under bundles, e.g.
content/blog/post/header.png
. This is handled by the.Resources
function. - Site resources: This is content located under
assets/
, e.g.assets/favicon-for-processing.png
. This is handled by theresources
function (notice the lack of a dot, since it’s always global and can’t have a different context).
Now that that’s out of the way, let’s get to the practical stuff…
Override Stylesheets
Sometimes, you want to uniquely style a single blog post, without needing to modify the main stylesheet, and you want to inline the styling into the HTML since the changes are usually pretty minimal. This is easy to achieve with page resources:
When ./override.css
exists, the <style>
element is included, with the stylesheet’s content inlined into it (safeCSS
marks the content as safe to use for styling, see the safeCSS
function’s documentation for more information), and this works for all bundles (e.g. content/blog/override.css
).
Inlined favicons
If your favicon is really small, and you’re looking to reduce the number of individual requests being made by your website (or just because you think it’s neat), you can inline it into your HTML as base64-encoded content. This is possible with site resources:
Whenever you change the image for assets/favicon.png
, the new favicon will be inlined automatically into the <link>
element, saving the extra favicon request in most cases. However, you should include favicon.png
under static/
as well, with a <link>
element that points to it, because a lot of RSS readers can’t parse inlined images.
Hugo variables in stylesheets
Yes, you read the description right, you can in fact put Hugo variables inside of stylesheets, and all it takes is copying the stylesheet from assets/
with the right functions. But first, here’s how resources copying normally works:
resources.Get
fetchesassets/before.css
.resources.Copy
copies it to/after.css
, which is under the homepage..Publish
executes the operation.
The problem with resources.Copy
is that it won’t expand any Hugo variables inside before.css
; it just copies it as is. But, let’s say before.css
contains this:
To copy before.css
to after.css
so that .Title is expanded, we can replace resources.Copy
with resources.ExecuteAsTemplate
, which would look like this:
Unlike resources.Copy
, resources.ExecuteAsTemplate
takes two arguments:
- The first argument is the path to the destination.
- And the second argument is the context passed to the template, much like how you’d specify
{{ partial "example.html" . }}
to pass the dot as the partial’s context.
In this case, after.css
is copied under the homepage, so .Title will be expanded to the homepage’s .Title value.
My use-case
I personally use this method to create count.css
files under each series term, where each stylesheet sets --total-pages: {{ .Pages.Len }};
, which avoids needing to update the HTML of all posts within a series whenever the total number of pages changes. Here’s what the copying for that looks like:
Additionally, the header partial is modified so the count.css
stylesheets are sourced whenever a post is apart of the relevant series:
In my actual partials, I additionally condition the
count.css
creation and sourcing on whether the number of pages under a term is greater than one, since, for what I use the information for, it doesn’t give me anything useful.Which looks like:
if and (eq (lower .Parent.Title) "series") (gt .Pages.Len 1)
, andif gt $termpage.Pages.Len 1
(inside therange .Params.series
function).