Automatic Responsive Images in Hugo: How the Built‑In Pipeline Works
Learn how Hugo’s extended edition automatically creates multiple image sizes and srcset markup from a single source file, removing the need for manual resizing.
19 Jun 2026, 11:37 UTC

Problem: Manual Image Resizing Slows Down Content
When preparing a blog post, authors often create several copies of the same picture at different widths (e.g., 400px, 800px, 1200px) and then write the srcset attribute by hand. This extra step adds time, introduces naming mistakes, and makes it easy to forget a size when the design changes.
How Hugo’s Built‑In Image Processing Works
Hugo’s extended edition bundles libvips, a fast image‑processing library. During site generation, any image placed in the assets/ folder can be accessed via resources.Get. Chaining transformation methods such as .Resize, .Fit, or .Crop creates new image resources on the fly. Each resource exposes fields like .RelPermalink (the public URL) and .Width/.Height, which you can use to build a srcset attribute automatically.
Configuration and Basic Usage
- Make sure you have the Hugo extended binary installed. Run
hugo versionand look for the word "extended" in the output. - Store your source images inside the
assets/directory of your project (e.g.,assets/photos/my-picture.jpg). - In a layout, shortcode, or markdown render hook, retrieve the image and apply the desired transformations:
{{ $src := resources.Get "assets/photos/my-picture.jpg" }}
{{ $img := $src.Resize "800x" }}
To generate a responsive srcset, you can create several widths and join them:
{{ $src := resources.Get "assets/photos/my-picture.jpg" }}
{{ $widths := slice "400" "800" "1200" }}
{{ $variants := slice }}
{{ range $widths }}
{{ $variants = $variants | append ($src.Resize (printf "%sx" .)) }}
{{ end }}
Worked Example: Figure Shortcode
Many themes ship a figure shortcode that already does the above. A simplified version looks like this:
{{/* figure shortcode */}}
{{ $src := resources.Get .Get "src" }}
{{ $widths := slice "400" "800" "1200" }}
{{ $variants := slice }}
{{ range $widths }}
{{ $variants = $variants | append ($src.Resize (printf "%sx" .)) }}
{{ end }}
{{ if .Get "caption" }}{{ .Get "caption" }}{{ end }}
When you call {{ /* figure src="assets/photo.jpg" alt="A scenic view" */ }} during hugo build, Hugo will produce files such as:
public/photos/photo.400x.jpgpublic/photos/photo.800x.jpgpublic/photos/photo.1200x.jpg
The resulting HTML will contain a srcset attribute that lists those three files with their widths, allowing the browser to pick the most appropriate size.
Trade‑offs and Limitations
- Extended binary required: The pipeline depends on libvips, which is only compiled into the Hugo extended edition. On minimal containers or systems without CGO support, you must fall back to manual resizing.
- Build time: Generating many variants increases the site build duration. For a site with hundreds of large source images, consider limiting the number of widths or using
.Quality 80to reduce file size. - Default quality: Hugo’s default JPEG quality is 82; if you need smaller files, add
.Quality 75(or another value) to the transformation chain.
Practical Verification Steps
- Confirm the extended version:
hugo versionshould output something likehugo v0.140.0 extended. - Run a full build:
hugo --minify. - Inspect the
public/folder for the generated image files (look for the width suffix in the filename). - Open the generated HTML page in a browser, right‑click the image, and choose “Inspect”. Verify that the
imgtag contains asrcsetattribute with the expected widths and that thesizesattribute matches your layout.
Actionable Closing
Switch to the Hugo extended edition, place your source images in assets/, and use the resources.Get pattern (or a figure shortcode) in your templates. After building, check the public/ directory for the auto‑generated variants and the srcset in the rendered HTML. You’ll get responsive images without maintaining multiple files or writing extra markup.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.