DEV Community

Clavin June
Clavin June

Posted on • Originally published at clavinjune.dev on

Image Processing Using Hugo

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.

{{- $src := .Get "src" -}}
{{- $alt := .Get "alt" -}}

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

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:

{{< img src="/img/testing/ehe.png" alt="alt" >}}
Enter fullscreen mode Exit fullscreen mode

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

{{- $alt := .Get "alt" -}}
{{- $res := resources.GetMatch (.Get "src") -}}

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

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:

...

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

...
Enter fullscreen mode Exit fullscreen mode

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

...

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

...
Enter fullscreen mode Exit fullscreen mode

Now you will get the output similar to this:

/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
Enter fullscreen mode Exit fullscreen mode

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:

<img srcset="
/url/to/480.png 480w,
/url/to/768.png 768w,
/url/to/1366.png 1366w,
/url/to/1920.png 1920w
" alt="alt">
Enter fullscreen mode Exit fullscreen mode

Let's generate it inside your shortcodes.

...

{{- $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 -}}

...
Enter fullscreen mode Exit fullscreen mode

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

...

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

...
Enter fullscreen mode Exit fullscreen mode

Then, use it as srcset attribute.

...

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

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:

...

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

Here is the complete source code of /layouts/shortcodes/img.html:

{{- $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>
Enter fullscreen mode Exit fullscreen mode

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

$ 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
Enter fullscreen mode Exit fullscreen mode

Thank you for reading!

Top comments (0)