Image Processing Using Hugo

tech · Oct 25, 2021 · ~5 min
Photo by @pascalwhoop on Unsplash
Photo by @pascalwhoop on Unsplash

Introduction

Since I migrated this blog from Jekyll to Hugo, I want to try all the features provided by Hugo. One of the features is image processing. It could help me to develop a mobile-friendly blog. An image processing might help you, who read these contents from a smartphone which might have a slow internet connection to load images faster.

Though I developed this blog as minimal as possible, processing an image might be a problem. That’s where Hugo’s feature helps me to create a solution for this problem. In this article, you will learn to implement image processing using Hugo.

Shortcodes

Shortcodes is one of Hugo’s feature that could help to reuse the implementation of image processing easily. You may want to read more about shortcodes here. Now let’s create one.

You may create your shortcodes in your Hugo project at either one of these paths:

  1. /layouts/shortcodes/<name>.html
  2. /themes/<theme>/layouts/shortcodes/<name>.html

You can create the shortcodes at /layouts/shortcodes/img.html.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{{- $src := .Get "src" -}}
{{- $alt := .Get "alt" -}}

<figure>
  <img
    src="{{ $src }}"
    alt="{{ $alt }}"
    width="100%"
    height="auto"/>
  <figcaption>{{ $alt }}</figcaption>
</figure>

Let’s say you have put your images in Hugo’s assets directory. For example, you put your image file in /assets/img/testing/ehe.png, and then you can use it at your content like this:

1
{{< img src="/img/testing/ehe.png" alt="alt" >}}

At the moment, Hugo will not render it yet. Let’s adjust the shortcode so it will render the image.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{{- $alt := .Get "alt" -}}
{{- $res := resources.GetMatch (.Get "src") -}}

<figure>
  <img
    src="{{ $res.RelPermalink }}"
    alt="{{ $alt }}"
    width="100%"
    height="auto"/>
  <figcaption>{{ $alt }}</figcaption>
</figure>

Now your image is rendered. Let’s create multiple versions of it with different widths.

Widths

Now define the widths you want to render. For example:

2
3
4
5
6
...

{{- $ws := slice 480 768 1366 1920 -}}

...

Then, iterate over it with Hugo’s resize function.

2
3
4
5
6
7
8
9
...

{{- range $ws -}}
    {{- $w := printf "%dx" . -}}
    {{- ($res.Resize $w).RelPermalink | safeURL -}}
{{- end -}}

...

Now you will get the output similar to this:

1
2
3
4
/img/testing/ehe_hudb6c5cbc207f47e5a1b3b7a3072e7a12_81266_480x0_resize_box_3.png
/img/testing/ehe_hudb6c5cbc207f47e5a1b3b7a3072e7a12_81266_768x0_resize_box_3.png
/img/testing/ehe_hudb6c5cbc207f47e5a1b3b7a3072e7a12_81266_1366x0_resize_box_3.png
/img/testing/ehe_hudb6c5cbc207f47e5a1b3b7a3072e7a12_81266_1920x0_resize_box_3.png

Those are your processed image URL with every width which you defined before. Now let’s use them inside your image’s source sets.

Source Set

To define srcset attribute on your image, you can use this format:

1
2
3
4
5
6
<img srcset="
/url/to/480.png 480w,
/url/to/768.png 768w,
/url/to/1366.png 1366w,
/url/to/1920.png 1920w
" alt="alt">

Let’s generate it inside your shortcodes.

 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
...

{{- $ws := slice 480 768 1366 1920 -}}
{{- $srcset := slice -}}
{{- range $ws -}}
    {{/* to avoid creating an image that is larger than the source */}}
    {{- if (le . $res.Width) -}}
        {{- $w := printf "%dx" . -}}
        {{- $url := ($res.Resize $w).RelPermalink | safeURL -}}
        {{- $fmt := printf "%s %dw" $url . -}}
        {{- $srcset = $srcset | append $fmt -}}
    {{- end -}}
{{- end -}}

...

Now you have your srcset format in a slice. You can join them using Hugo's delimit function.

14
15
16
17
18
...

{{- $set := delimit $srcset "," -}}

...

Then, use it as srcset attribute.

16
17
18
19
20
21
22
23
24
25
26
...

<figure>
  <img
    srcset="{{ $set }}"
    src="{{ $res.RelPermalink }}"
    alt="{{ $alt }}"
    width="100%"
    height="auto"/>
  <figcaption>{{ $alt }}</figcaption>
</figure>

Lastly, let’s make the HTML render the image according to the viewport width.

sizes

To define sizes attribute on your image, you can use this format:

16
17
18
19
20
21
22
23
24
25
26
27
...

<figure>
  <img
    srcset="{{ $set }}"
    sizes="(max-width: 480px) 480px, 100vw"
    src="{{ $res.RelPermalink }}"
    alt="{{ $alt }}"
    width="100%"
    height="auto"/>
  <figcaption>{{ $alt }}</figcaption>
</figure>

Here is the complete source code of /layouts/shortcodes/img.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
{{- $alt := .Get "alt" -}}
{{- $res := resources.GetMatch (.Get "src") -}}

{{- $ws := slice 480 768 1366 1920 -}}
{{- $srcset := slice -}}
{{- range $ws -}}
    {{/* to avoid creating an image that is larger than the source */}}
    {{- if (le . $res.Width) -}}
        {{- $w := printf "%dx" . -}}
        {{- $url := ($res.Resize $w).RelPermalink | safeURL -}}
        {{- $fmt := printf "%s %dw" $url . -}}
        {{- $srcset = $srcset | append $fmt -}}
    {{- end -}}
{{- end -}}

{{- $set := delimit $srcset "," -}}

<figure>
  <img
    srcset="{{ $set }}"
    sizes="(max-width: 480px) 480px, 100vw"
    src="{{ $res.RelPermalink }}"
    alt="{{ $alt }}"
    width="100%"
    height="auto"/>
  <figcaption>{{ $alt }}</figcaption>
</figure>

Now if you build your Hugo site, you will see your images is auto-generated.

1
2
3
4
5
6
7
8
9
$ tree img/
img/
└── testing
    ├── ehe_hudb6c5cbc207f47e5a1b3b7a3072e7a12_81266_1366x0_resize_box_3.png
    ├── ehe_hudb6c5cbc207f47e5a1b3b7a3072e7a12_81266_480x0_resize_box_3.png
    ├── ehe_hudb6c5cbc207f47e5a1b3b7a3072e7a12_81266_768x0_resize_box_3.png
    └── ehe.png

1 directory, 4 files

Thank you for reading!

· · ·

Love This Content?

Any kind of supports is greatly appreciated! Kindly support me via Bitcoin, Ko-fi, Trakteer, or just continue to read another content. You can write a response via Webmention and let me know the URL via Telegraph.

Drop Your Comment Below