Automated image handling and processing in Hugo

Guide for automated image processing in Hugo - static website engine. Learn how to resize and convert images, to speed up your build process and fallback solutions.

Author: Markus A. Wolf
Updated: August 2021

If you want to know more about different ways to get access to images in the content or assets folder - check out this tutorial .

Resize, fill and fit into your format

Hugo does support different ways to resize your images. The method .Resize supports fixed width and height as much as it supports if you only define the height or width. If you define only the height or width the aspect ratio will be still the same but in case you define width and height, the aspect ratio will change to the new image size.

The methods .Fill and .Fit are behaving very similar to the CSS object-fit property. In this case contain would be .Fit and cover .Fill. For both methods you need to define width and height and the aspect ratio is always adhered to.

<div class="my-24">
    {{ $buffer := .Page.Resources.GetMatch "example.jpg" }}
    {{ $image_resize := $buffer.Resize "400x" }}
    <img src="{{ $image_resize.RelPermalink }}" alt="">
    {{ $image_fit := $buffer.Fit "300x300" }}
    <img src="{{ $image_fit.RelPermalink }}" alt="">
    {{ $image_fill := $buffer.Fill "300x300" }}
    <img src="{{ $image_fill.RelPermalink }}" alt="">
</div>

Define the quality and change the format of your image resources

Hugo supports the following formats: JPG, PNG, TIF, BMP, GIF and WebP (since version 0.83.0). Changing the quality to save some storage is only supported for the formats JPG and WebP.

Supported options

Hugo supports the following options for .Resize, .Fill and .Fit:

  • Background color: #3A5A8E - if you have a transparent PNG and want to convert this to JPG.
  • Quality: q50 - if you want to change the compression for a format (only supported by JPG and WebP)
  • Format: jpg - If you want to change the format of your image. (jpg, gif, png, bmp, tif, webp)
  • Rotate: r45 - If you want to rotate the image
  • Anchor: Center - If you want to define where the main motive is located. Only supported by the .Fill method. (Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight)
  • Resample: Box - If you want to change the default resampling filter for downscaling images. You can find out more about it in the imaging documentation .
  • Hint: photo - Hint about what type of image this is. Currently only used when encoding to WebP. (picture, photo, drawing, icon, text)
<div class="my-24">
    {{ $buffer_png := .Page.Resources.GetMatch "example.png" }}
    {{ $buffer_jpg := .Page.Resources.GetMatch "example.jpg" }}
    {{ $image_jpg := $buffer_jpg.Resize "400x jpg q10" }}
    <img src="{{ $image_jpg.RelPermalink }}" alt="">
    {{ $image_png := $buffer_png.Resize "400x jpg q40 #3A5A8E Lanczos" }}
    <img src="{{ $image_png.RelPermalink }}" alt="">
    {{ $image_png_rotate := $buffer_png.Resize "400x jpg q10 #3A5A8E r45" }}
    <img src="{{ $image_png_rotate.RelPermalink }}" alt="">
    {{ $image_png_rotate_fill := $buffer_png.Fill "400x400 webp #3A5A8E r45 Smart" }}
    <img src="{{ $image_png_rotate_fill.RelPermalink }}" alt="">
    {{ $image_webp := $buffer_png.Resize "400x webp drawing" }}
    <img src="{{ $image_webp.RelPermalink }}" alt="">
</div>

As a fallback for different formats you can define a global background color if you have a transparent PNG and convert this to JPG.

How to handle different formats

If you want to use automated resizing and support different image formats like SVG you have to check if the image is resizable. Hugo gives you some quite nice ways to do this. In the following example I use a front matter variable and check if the format is in the list of support formats.

<div class="my-24">
    {{ $buffer := .Page.Resources.GetMatch .Params.cover }}

    {{ if strings.HasSuffix $buffer "svg" }}
        Image is SVG
    {{ end }}

    {{ if in $buffer.MediaType.Suffixes "svg" }}
        Image is SVG
    {{ end }}

    {{ if in (slice ".jpg" ".jpeg" ".png") (path.Ext $buffer) }}
        Image is resizable
    {{ end }}

    {{ if in (slice "jpg" "gif" "png") (index $buffer.MediaType.Suffixes 0) }}
        Image is resizable
    {{ end }}
</div>

Caching and speed up your build time

Image processing needs time and can increase your build time enormously. Hugo does have a built-in garbage collector for processed images. By default every processed image gets stored in the /resources folder. During the build process Hugo checks if there is an up-to-date processed image and uses it instead of re-processing it. To speed up your build time you should add the /resources folder to your Git repository. The result will be a more than 90% faster build time depending on your image count and sizes.

Configuration - Setting up some defaults

You can change the default image processing options in your Hugo configuration file.

[imaging]
resampleFilter = "box"
quality = 75
hint = "photo"
anchor = "smart"
bgColor = "#ffffff"
[imaging.exif]
includeFields = ""
excludeFields = ""
disableDate = false
disableLatLong = false

You can find more about the default configuration in the Hugo documentation .

All links in a practical list

More articles

Thoughts, topics or just solutions I would like to make available to you, colleagues and fellow enthusiasts.