A few days ago, the Hugo dev team issued the latest version of this site’s static site generator (SSG). Hugo 0.81.0 added a number of goodies, as you would expect from a “dot-zero” upgrade, but one in particular has simplified my writing for this site.
Perhaps it’s more accurate to say that the addition restored something I’d thought I couldn’t have any more: the use of attributes within the site’s Markdown content to simplify the invocation of classes.
For those of you who haven’t used this capability before, let me explain.
A boxing exercise
Back when this site was on Eleventy, I could write the following Markdown, invoking the site’s box
class with an curly-bracketed attribute at the end:
**Important**: This is a paragraph that goes in a box so it'll attract attention.{.box}
. . . and this would be the result:
Important: This is a paragraph that goes in a box so it’ll attract attention.
The alternative would be actually writing HTML within the Markdown, but that wasn’t as convenient when it was necessary to add things like links and formatting:
<p class="box"><strong>This</strong> is bold and <em>this</em> is italicized/obliqued, and <a href="https://gohugo.io/documentation" rel="noopener">this link</a> goes to the Hugo documentation, while <a href="/posts/2021/02/simplify-simplify">this post link</a> goes to the site’s recent <strong>“Simplify, simplify”</strong> post.</p>
. . . instead of just writing this in Markdown:
**This** is bold and *this* is italicized/obliqued, and [this link](https://gohugo.io/documentation) goes to the Hugo documentation, while [this post link](/posts/2021/02/simplify-simplify/) goes to the site's recent **"Simplify, simplify”** post.{.box}
. . . to get the same result:
This is bold and this is italicized/obliqued, and this link goes to the Hugo documentation, while this post link goes to the site’s recent “Simplify, simplify” post.
In Eleventy, I enjoyed this convenience through use of the Markdown-it-attrs plugin for the Markdown-it parser. In Eleventy, you essentially put together your chosen parser with whatever plugins it needs to do what you want — footnoting, “smart” punctuation, and, yes, handling styling attributes.
When I came back to Hugo, I figured I’d lost this convenience because Hugo’s built-in Markdown parser, goldmark, is limited to allowing attributes for only headings.1 I compensated by putting together shortcodes to insert the two classes I most frequently had used with attributes in Eleventy: the aforementioned box
class for my “Hey-look-at-this” items and the imgcCaption
2 class I used for captions under in-body images. It wasn’t as convenient, but it worked:
{{< imgc src="BW-holding-Kennedy-first-night__crop_1008x712.jpg" alt="Bryce Wray holds his new granddaughter, Kennedy Beck, on the night of her birth" width="1008" height="712" >}}
{{% imgcCapt %}}Your faithful correspondent holds his first grandchild for the first time, on the first night of her life. Enough "firsts" for you there?{{% /imgcCapt %}}
. . . to produce the following result (borrowed from last year’s “Welcome, sweet little early bird” post about the slightly premature birth of our granddaughter, who’s nearing her first birthday):

Your faithful correspondent holds his first grandchild for the first time, on the first night of her life. Enough “firsts” for you there?
Hugo 0.81.0 as a labor-saving device
But then Hugo 0.81.0 arrived, with enhanced attribute support that goes well beyond that from goldmark itself:
Hugo already supports adding attribute lists (e.g CSS classes) after titles. We now also allow adding attribute lists after Markdown blocks, e.g. tables, lists, paragraphs etc. [sic]
To get that working in Hugo as of v.0.81.0, just make appropriate edits to your config file’s markup
section. For example, here’s how I have markup
set in this site’s config.yaml
file (note that block
is true
, which enables what I’m discussing in this article):
markup:
highlight:
guessSyntax: true
noClasses: false
tabWidth: 2
goldmark:
extensions:
linkify: false
parser:
attribute:
block: true
title: true
autoHeadingID: true
# otherwise, can't use (e.g.) "Content" as a heading
renderer:
unsafe: true
# only to allow for inline HTML and/or JS
# ... other desired settings are defaults
So, now, all I have to do to get that same caption is:
Your faithful correspondent holds his first grandchild for the first time, on the first night of her life. Enough "firsts" for you there?
{.imgcCaption}
The only difference from how I did it in the Eleventy/plugins combo is that, in Hugo, it requires a line feed between the end of what you’re styling and the attribute (in this case, {.imgcCaption}
to specify use of the imgcCaption
class). Hardly a biggie. (With the Eleventy setup, you can put a line feed there, too, so that’s even better for cross-site/cross-repo purposes, for those of you like me who are so inclined.)
A little thing to some, but . . .
To others, this enhancement may seem trivial. For me, it makes it easier and faster to write, especially when I’m doing a more technical piece that requires multiple box
instances to focus your attention on gotchas, or when I’m adding updates to older posts (as I often do).
I certainly can write stuff in HTML when needed. I’ve been doing it for a quarter of a century. Still: if I can do the same thing in Markdown, and far more quickly, why not?
So, thanks to this new enhanced attributes capability (and some fairly painless searching/replacing within the appropriate posts), I was able to retire both the box
and imgcCapt
shortcodes in favor of the simpler, more quickly typed attributes for the classes they invoked. And, as I have need to call more CSS from Markdown over time, this capability will continue to make that a comparative breeze.
Easier and faster ===
better. I’m grateful to the Hugo dev team for adding this functionality to Hugo in version 0.81.0 — and will be in the future every time I can add, HTML-free, some boxed text, or an image caption, or any other item that needs special handling in CSS.
You also can configure Hugo to use its previous Markdown parser, Blackfriday, but it doesn’t do the attributes thing at all. Moreover, Blackfriday support in Hugo is being deprecated in the not-too-distant future. ↩︎
In Eleventy, I’d called this class
lazypicturecaption
as a reference to thelazypicture
shortcode I used in concert with lazy-loading-specific JavaScript to produce responsive images. In Hugo, I’ve dispensed with that JavaScript, using animgc
shortcode for responsive images (relying instead on browsers’ native lazy-loading) — hence, the different name in Hugo for what essentially is the same thing, namely a caption-styling class. ↩︎
Latest commit (ddfbbdb6
) for page file:
2023-09-22 at 10:57:57 AM CDT.
Page history