Hugo: How to add support for responsive images trough image processing and page bundles <3

I built a Hugo shortcode for automatically generating image versions to support the img srcset attribute for responsive images. Here’s a quick guide on how to do it for yourself.

Step one: Add a shortcode

I had to tinker a bit to figure out how page resources work. So, here’s how to do it.

Create a shortcode by creating a file within /layouts/shortcodes/bundle-image.html. And within that file add:

hello from the shortcode
<!-- Within a shortcode we need $.Page to reach the page's resources. -->
{{ range $.Page.Resources }}
<li><a href="{{ .RelPermalink }}">{{ .ResourceType | title }}</a></li>
{{ end }}

Now try out the shortcode out by writing {{< bundle-image >}} within a blog post. Hopefully you’ll see hello from the shortcode printed out. But you probably won’t see any resources yet. You’ll need to create a page resource for that (see file structure example).

Essentially, you’ll need to create a folder similar to this:

  • post/blog-post-name/index.md
  • post/blog-post-name/some-image.jpg

So, you put index.md and some-image.jpg within the same folder. If you use the shortcode in index.md, you should now see the image listed out. It’s important that the file is called index.md.

Step two: Add img srcet functionality

At this point we’ve successfully enabled page resources functionality and created a nifty shortcode. Time to upgrade it with some img srcset goodness!

Replace the shortcode content in bundle-image.html with this:

{{ $altText := .Get "alt"}}
{{ $caption := .Get "caption"}}
{{ with $.Page.Resources.GetMatch (.Get "name") }}
  <figure>
    <a href="{{.RelPermalink}}">
      <img
        srcset="
          {{ (.Resize "320x").RelPermalink }} 320w,
          {{ (.Resize "600x").RelPermalink }} 600w,
          {{ (.Resize "1200x").RelPermalink }} 2x"
        src="{{ (.Resize "600x").RelPermalink }}" alt="{{$altText}}"/>
    </a>
    <figcaption><p>{{ $caption }}</p></figcaption>
  </figure>
{{ else }}
  could not find image
{{ end }}

We can now write the shortcode like so:

Some blogpost content.

{{< bundle-image name="picture.jpg" alt="Description for screen readers." caption="Some caption" >}}

More content.

The above shortcode will now output a img tag with four automatically generated images, populating one srcset attribute, alongside one plain src attribute as fallback. We tie the bow with link to the full size image.

If this guide helped you out, give me a shoutout on Twitter. :)