Generating responsive images on a static Hugo website
Dec 06, 2022
For years and years I’ve been using Jekyll as my static site generator of choice, mostly because I like their templating engine and I’m a fan of Ruby as a programming language. I’ve been experimenting with Hugo as well, but it never really clicked for me. Well, until I found the perfect theme for my needs. The same theme is now used here and on the toot.community blog so I wanted to set mine apart a little bit by adding banner images on some posts. Downloading an image from Unsplash and manually resizing it wasn’t an option though - I need things to be frictionless when I want to add a blog entry.
I started looking for ways to automatically generate multiple sizes of an image and came across a lot of different solutions. Most didn’t work anymore or were very convoluted. That’s to say, until I found Bryce Wray’s entry.
I quickly adapted his code to my needs and had it working on no-time, you can see it in action right here.
Here’s how I did it.
Assets directory
In order to leverage the built-in image resizing capabilities of Hugo, you have to create an assets/images
directory in the root of your project. Any other place doesn’t work, unless of course you customize the directory. But I like using defaults to avoid breakage later down the line.
Shortcodes
The following Hugo shortcode will generate multiple sizes of a given image and spit out .webp and .jpeg files.
Create a file called /layouts/shortcodes/imgh.html
in the root of your project with the following contents.
{{- $respSizes := slice "960" "1280" "1920" -}}
{{- $imgBase := "images/" -}}
{{- $src := resources.Get (printf "%s%s" $imgBase (.Get "src")) -}}
{{- $alt := .Get "alt" -}}
{{- $divClass := "" -}}{{/* Init'g */}}
{{- $imgClass := "w-full h-auto animate-fade" -}}
{{- $dataSzes := "(min-width: 1024px) 100vw, 50vw" -}}
{{- $actualImg := $src.Resize "640x jpg" -}}
<picture>
<source
type="image/webp"
srcset="
{{- with $respSizes -}}
{{- range $i, $e := . -}}
{{- if ge $src.Width . -}}
{{- if $i }}, {{ end -}}{{- ($src.Resize (printf "%sx%s" . " webp") ).RelPermalink }} {{ . }}w
{{- end -}}
{{- end -}}
{{- end -}}"
sizes="{{ $dataSzes }}"
/>
<source
type="image/jpeg"
srcset="
{{- with $respSizes -}}
{{- range $i, $e := . -}}
{{- if ge $src.Width . -}}
{{- if $i }}, {{ end -}}{{- ($src.Resize (printf "%sx%s" . " jpg") ).RelPermalink }} {{ . }}w
{{- end -}}
{{- end -}}
{{- end -}}"\
sizes="{{ $dataSzes }}"
/>
<img class="{{ $imgClass }}"
src="{{ $actualImg.RelPermalink }}"
width="{{ $src.Width }}"
height="{{ $src.Height }}"
alt="{{ $alt }}"
loading="lazy"
/>
</picture>
</div>
Using the shortcode
Now in order to use the above shortcode you can simply drop an image into /assets/images
and insert this line of code in your MarkDown file.
{{< imgh src="my-example-file.jpeg" alt="My example file" >}}