Hugo Picture Shortcode With Multiple Sources

A Hugo shortcode using the HTML picture element to enable different formats for the same image

4 minute read

A while ago I published this post about a better figure shortcode for Hugo that enabled lazy loading. Today, I bring you yet another update on the same shortcode. This time around, the focus is on leveraging the HTML picture element, which enables alternative versions of the same image in different formats, leaving the browser to decide which one to use. You can serve the same image in, for instance, JPEG-XL and plain old JPEG at the same time. The browser will read the tag, and select the appropriate image depending on its capabilities. If you use a JPEG-XL-capable browser (Thorium, Pale Moon, Basilisk, Waterfox, LibreWolf, Firefox Nightly), you will be served the smaller JPEG-XL version, otherwise you will get the plain JPEG version.

Here is how to use the shortcode in your Hugo posts and pages:

{{< fig 
        src1="/img/2023/02/jxl-avif/support-jxl-yes.jxl"
        type1="image/jxl" 
        src="/img/2023/02/jxl-avif/support-jxl-no.jpg" 
        class="fig-center" 
        width="50%" 
        loading="lazy" >}}

The above snippet results in the following, once rendered. You should either see “Your browser does not support JPEG-XL” in black, or “Your browser supports JPEG-XL” in green:

You can include up to four sources (src1, src2, etc.), with their corresponding types. Here is the Hugo shortcode file. You need to save it in the file themes/[themename]/layouts/shortcodes/fig.html.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<!-- 
    Same as Hugo's base 'figure' shortcode with the image loading attribute.
    This enables lazy loading of images. Additionally, this uses the 'picture'
    tag to enable multiple versions of the same image with different formats.
    The browser selects the image with the first supported format.

    Attributes:
    - src      - path to default source image
    - width    - width img attribute
    - height   - height img attribute
    - loading  - loading img attribute
    - title    - description/caption
    - src1     - alternative source (1)
    - type1    - type of src1
    - src2     - alternative source (2)
    - type2    - type of src2
    - src3     - alternative source (3)
    - type3    - type of src3
    - src4     - alternative source (4)
    - type4    - type of src4
-->
<figure{{ with .Get "class" }} class="{{ . }}"{{ end }}>
    {{- if .Get "link" -}}
        <a href="{{ .Get "link" }}"{{ with .Get "target" }} target="{{ . }}"{{ end }}{{ with .Get "rel" }} rel="{{ . }}"{{ end }}>
    {{- end -}}
    <picture>
      {{- if .Get "src1" }}
      <source srcset="{{ .Get "src1" }}"{{ with .Get "type1" }} type="{{ . }}"{{ end }} />
      {{ end -}}
      {{- if .Get "src2" }}
      <source srcset="{{ .Get "src2" }}"{{ with .Get "type2" }} type="{{ . }}"{{ end }} />
      {{ end -}}
      {{- if .Get "src3" }}
      <source srcset="{{ .Get "src3" }}"{{ with .Get "type3" }} type="{{ . }}"{{ end }} />
      {{ end -}}
      {{- if .Get "src4" }}
      <source srcset="{{ .Get "src4" }}"{{ with .Get "type4" }} type="{{ . }}"{{ 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 -}}
         {{- with .Get "loading" }} loading="{{ . }}"{{ end -}}
         decoding="async" />
    </picture>
    {{- if .Get "link" }}</a>{{ end -}}
    {{- if or (or (.Get "title") (.Get "caption")) (.Get "attr") -}}
        <figcaption
         {{- with .Get "width" }} style="margin: 0 auto; width:{{ . }};"{{ end -}}
            >
            {{ with (.Get "title") -}}
                <h4>{{ . }}</h4>
            {{- end -}}
            {{- if or (.Get "caption") (.Get "attr") -}}<p class="fig-attribution">
                {{- .Get "caption" | markdownify -}}
                {{- with .Get "attrlink" }}
                    <a href="{{ . }}">
                {{- end -}}
                {{- .Get "attr" | markdownify -}}
                {{- if .Get "attrlink" }}</a>{{ end }}</p>
            {{- end }}
        </figcaption>
    {{- end }}
</figure>

Here is a link to the source file: fig.html.

Website design by myself. See the privacy policy.
Content licensed under CC-BY-NC-SA 4.0 .