https://mijndertstuij.nl/posts/hugo-responsive-images-using-render-hooks/
Mijndert Stuij
* Blog
* About
* Explore
Responsive images in Hugo using Render Hooks
April 9, 2026
Back in 2022 I wrote about automatically generating responsive images
in both JPEG and WebP formats using Hugo shortcodes. In those days,
browser support for WebP was still quite spotty so we had to generate
both formats and do a little magic to let the browser fall back to
JPEG if needed.
Fast forward to 2026 and WebP is now well supported in all major
browsers, and Hugo has also evolved beyond shortcodes in favor of
Render Hooks.
The render hook
The actual render hook that generates the resized JPEG and WebP files
looks pretty similar to the shortcode, but works slightly
differently.
Create a file in layouts/_default/_markup/render-image.html with the
following contents:
{{- $src := .Destination -}}
{{- $alt := .Text -}}
{{- $img := .Page.Resources.GetMatch $src -}}
{{- if not $img -}}
{{- $img = resources.Get $src -}}
{{- end -}}
{{- if $img -}}
{{- $widths := slice 480 768 1024 1366 1920 -}}
{{- $origWidth := $img.Width -}}
{{- $origHeight := $img.Height -}}
{{- $srcsetEntries := slice -}}
{{- range $w := $widths -}}
{{- if le $w $origWidth -}}
{{- $resized := $img.Process (printf "resize %dx webp q85" $w) -}}
{{- $srcsetEntries = $srcsetEntries | append (printf "%s %dw" $resized.RelPermalink $w) -}}
{{- end -}}
{{- end -}}
{{- $fallbackWidth := 1024 -}}
{{- if lt $origWidth 1024 -}}
{{- $fallbackWidth = $origWidth -}}
{{- end -}}
{{- $fallback := $img.Process (printf "resize %dx jpg q85" $fallbackWidth) -}}
{{- else -}}
{{- end -}}
As you can see, the element is no longer used, and instead
we directly generate the srcset attribute for the
tag and
reference the WebP file, with a fallback to the JPEG file in the
event the browser doesn't support WebP.
The post and image files
Then in a blog post, likely a Markdown file, you can reference the
image like any other and the Render Hook will take care of the rest:

My previous post suggested to put the images in the /assets/images/
directory, but with the Render Hook in place and using the latest
Hugo version, you can use something called page bundles. This means
you put the images right next to the Markdown file in the same
directory.
content/posts/my-post/
index.md
hero.jpg
Setting WebP image quality
In your Hugo configuration file, you can set the default quality for
WebP images using the imaging configuration. For example:
[imaging]
quality = 85
[imaging.webp]
quality = 85
Wrapping up
Compared to the shortcode approach this is a nice simplification.
Gone is the element, the shortcode is gone, just standard
Markdown and a single modern Render Hook. Page bundles also make it
easier to keep things organized since images live right next to the
content.
Related posts
Responsive images on a static Hugo website
How to set up automatic responsive image resizing in Hugo using
shortcodes, generating optimized WebP and JPEG files for your static
site
Read post
* RSS
* Mastodon
* GitHub
(c) 2026 Mijndert Stuij