Changing Hugo's built-in figure shortcode to add lazy loading to images

Viewed 246

In my Hugo-generated website I'm making use of the built-in shortcode figure. Example:

{{< figure src="myImage.svg" width="100%" alt="Some description" >}}

This renders the following HTML:

<figure>
    <img src="myImage.svg"
         alt="Some description" width="100%"/> 
</figure>

But now I'm trying to update my Hugo website in such way that the figure shortcode adds the loading=lazy attribute to the img tag:

<figure>
    <img 
         loading="lazy"
         src="myImage.svg"
         alt="Some description" width="100%"/> 
</figure>

How can I achieve my goal of letting images be loaded lazily using the (new) loading attribute?

2 Answers

You can create a file named layouts\shortcodes\figure.html and copy the contents of Hugo's figure shortcode source code into this file. Here's the current source code:

<figure{{ with .Get "class" }} class="{{ . }}"{{ end }}>
    {{- if .Get "link" -}}
        <a href="{{ .Get "link" }}"{{ with .Get "target" }} target="{{ . }}"{{ end }}{{ with .Get "rel" }} rel="{{ . }}"{{ end }}>
    {{- end -}}
    <img src="{{ .Get "src" }}"
         {{- if or (.Get "alt") (.Get "caption") }}
         alt="{{ with .Get "alt" }}{{ . }}{{ else }}{{ .Get "caption" | markdownify| plainify }}{{ end }}"
         {{- end -}}
         {{- with .Get "width" }} width="{{ . }}"{{ end -}}
         {{- with .Get "height" }} height="{{ . }}"{{ end -}}
    /><!-- Closing img tag -->
    {{- if .Get "link" }}</a>{{ end -}}
    {{- if or (or (.Get "title") (.Get "caption")) (.Get "attr") -}}
        <figcaption>
            {{ with (.Get "title") -}}
                <h4>{{ . }}</h4>
            {{- end -}}
            {{- if or (.Get "caption") (.Get "attr") -}}<p>
                {{- .Get "caption" | markdownify -}}
                {{- with .Get "attrlink" }}
                    <a href="{{ . }}">
                {{- end -}}
                {{- .Get "attr" | markdownify -}}
                {{- if .Get "attrlink" }}</a>{{ end }}</p>
            {{- end }}
        </figcaption>
    {{- end }}
</figure>

After that you can make the required changes to your local figure.html. For instance:

...
    <img src="{{ .Get "src" }}" loading="lazy" decoding="async"
...

Hugo prefers your locally defined shortcode over its built-in version, meaning that this overrides the built-in behavior.

Render image hooks would be a safe/better bet, then you can keep to standard markdown in your md file.

So, in layouts/_default/_markup (as per whatever lookup order you require, this would be a global setup)

render-image.html

<figure>
    <img 
         loading="lazy"
         src=".Destination"
         alt=".Text" width="100%" title=".Title"/> 
</figure>

In your markdown file:

![]() <- typical markdown image link

Docs: https://gohugo.io/templates/render-hooks/

Related