Skip to main content

Enriching your articles with Hugo

Hugo has some tricks to enrich the contents of the posts and is highly customizable. With some imagination, one can implement features that are in no way inferior to some popular CMS out there.


Table Of Contents


Table of contents

When writing a long post, a table of contents can be quite useful to quickly access parts of the article. Hugo comes with a TableOfContents module by default. We’re going to use something called shortcodes. Shortcodes allow you to write small snippets of code that are triggered with a macro. This way we can optionally add a table of contents.

We’re gonna create a file layouts/shortcodes/toc.html with the following content:

<hr>
<h1>Table Of Contents</h1>
<div class="toc">
    {{ .Page.TableOfContents }}
</div>
<hr>

Next time we add {{ toc }} inside a Markdown file, it will insert a new table of contents in that place.

Add captions to images

Another useful feature is having descriptions of the images inserted. In this case we are going to take advantage of the title property of the img tag.

We are also going to take advantage of the Markdown syntax for inserting images: While the usual way to inserting images is like this ![Alt text](location), you can also add a title that will not be displayed like this ![Alt text](location "my description").

Create this file: layouts/_default/_markup/render-image.html

{{ if .Title }}
  <figure>
    <img src="{{ .Destination | safeURL }}" alt="{{ .Text }}">
    <figcaption>{{ .Title }}</figcaption>
  </figure>
{{ else }}
  <img src="{{ .Destination | safeURL }}" alt="{{ .Text }}">
{{ end }}

Now you can add images with captions whenever you want, jump to the next section to see an example of an image with such feature.

Invert (some) diagrams and images on dark mode

This is a greeeat feature 👌, especially for the actual users of dark mode, so they don’t get blinded with white squares!. Again we are going to use shortcodes. This shortcode is pretty simple, when used, the content inside will be surrounded by an .invert class, just add this snippet of code to layouts/shortcodes/invert.html

<div class="invert" >{{ .Inner | markdownify }}</div>

You will also need to do something with that class. In my case I went to my theme’s css, located in themes/mytheme/assets/css/main.css. Inside the dark mode condition, we will insert this code, which will invert the images located inside that class:

@media (prefers-color-scheme: dark) {
    .invert img {
        -webkit-filter: invert(85%); /* safari 6.0 - 9.0 */
                filter: invert(85%);
    }
}

Finally, in any Markdown document you could insert the following tag, and automatically that image will be inverted, useful for diagrams, not that much for photos. That’s why we don’t want to always apply the inversion:

{{< invert >}}
![Alt Txt](/img/test.svg)
{{< /invert >}}

Here’s an example: (try toggling your system to dark/light mode!)

Alt Txt
This diagram will adapt to the theme of the page

Update: alert boxes

Alert boxes are the definitive tool to catch the attention of the reader. Particularly when everything has gone out of hand and we may break things 😂.

Add this snippet of code to layouts/shortcodes/notice.html:

<div class="notice {{ .Get 0 }}">
    {{ if (or (eq (.Get 0) "alert" ) (eq (.Get 0) "warning")) }}
    <span class="icon alert">
        <object data="/icons/alert.svg" width="24" height="24"></object>
    </span>
    {{ else if (eq (.Get 0) "info")}}
    <span class="icon info">
        <object data="/icons/info.svg" width="24" height="24"></object>
    </span>
    {{ else }}
    <span class="icon info">
        <object data="/icons/info.svg" width="24" height="24"></object>
    </span>
    {{ end }}
    <p>{{ .Inner | markdownify }}</p>
</div>

With css you can customize it a little bit:

.notice {
    position: relative;
    border-radius: 6px;
    margin-bottom: 5px;
}

.notice.alert, .notice.warning {
    background-color: var(--warning-bg-color);
    border: solid 1px rgb(164, 27, 27);
}

.notice.info {
    background-color: var(--info-bg-color);
    border: solid 1px rgb(21, 81, 170);
}

.notice p {
    padding: 0 0.8em 0 2em;
}

.icon.alert, .icon.info {
    position: absolute;
    top: 0.6rem;
    left: 0.5rem;
}

You can use it in a post like this:

{{<notice warning>}}
This is a warning
{{</notice>}}

Aaand, this is the final result 🎉:

This is a warning

This is an info block. (You can use markdown code)

This is a note block. (You can use markdown code)

Sources

ruddra | sebastiandedeyne