July 4, 2022
Speaking at HugoConf 2022
It has been an honor to speak at HugoConf 2022. My lightning talk was about image resizing. Hugo is known for its fast page loads, but if you want instantly loading webpages, you also need to resize your images properly. Fortunately Hugo can do that by itself.
In this talk I explain how to configure Hugo so that it automatically resizes and compresses all images in your project, even the ones that are uploaded through an external CMS by your client.
This was my second conference talk, after JekyllConf 2019. Below you find the written version of the talk, so you can copy and paste the code.
1. Choose your method
First you need to choose your resizing and compression method. I like to keep things simple. Therefore I always use the one image technique, where you use an oversized, heavily compressed jpg image. A typical image is two to ten times smaller than its original, while the image tag looks as simple as this:
<img src="large_heavily_compressed.jpg" />
2. Set the asset directory
Hugo resizes images during the build process. However, Hugo can only resize images that live in an assigned ‘asset directory’. I store all my images in the ‘static’ folder, so I always define my static folder to be the asset directory. You can do this by adding the following line to your configuration file:
assetDir: static
3. Create a compression rule
Now we can start. Let us assume that your front matter looks like this:
---
title: My first post
image: /path/to/my/image.jpg
---
Your path is stored in a front matter variable, thus in .Params.image. This could be a featured image that you want to use in the header of your post. To find the corresponding file, we use a Hugo variable called resources (without a capital). Because we have set the asset directory to the static folder, this variable contains everything in your static directory. You can target an individual resource with a GetMatch statement in combination with the path to your image:
resources.GetMatch .Params.image
Next you have to choose a resize strategy. This can be Resize, Fit, Fill or Crop. In this example I use Fit to make sure my image is always smaller than 600 pixels on each side. I use a ‘Smart’ crop and 50% image quality, as explained in the one image technique:
(resources.GetMatch .Params.image).Fit "600x600 jpg Smart q50"
Finally you probably want the relative URL to this image. You get it by adding .RelPermalink and wrapping the whole thing in brackets:
((resources.GetMatch .Params.image).Fit "600x600 jpg Smart q50").RelPermalink
The above code results in a URL that points to a resized version of the original image. But if the original image does not exist (anymore), Hugo will throw an error. Therefore it is smart to check the existence of the resource first, by wrapping everything in an if statement:
{{ if (resources.GetMatch .Params.image) }}
<img src="{{ ((resources.GetMatch .Params.image).Fit `600x600 jpg Smart q50`).RelPermalink }}" />
{{ end }}
4. Create a render hook
Now we have resized images in our layout. But what about the images in the content? For images in the markdown you can use a ‘render hook’. This is a file that describes how markdown images are rendered. Create the following file:
/layouts/_markup/render-image.html
… and put this logic inside:
{{ with (resources.GetMatch .Destination) }}
{{ if ne .MediaType.SubType "svg" }}
<img src="{{ (.Resize `900x jpg Smart q50`).RelPermalink | safeURL }}" alt="{{ $.Text }}" />
{{ else }}
<img src="{{ .RelPermalink | safeURL }}" alt="{{ $.Text }}" />
{{ end }}
{{ end }}
Note that we use .Destination for the path of the original image and .Text for the alt text defined in the markdown. Once you have added this render hook, all images in your Hugo project will be resized: the ones in your layouts and the ones in your content.
More about image resizing
Apart from my talk, HugoConf 2022 hosted some other interesting image-related talks. They are all worth watching:
- Making Image Uploads Faster with Figmage by Ravi Lingineni
- Custom Shortcodes for the Win by Chris Griffing
- How to Achieve Perfect Google Lighthouse Scores Using Hugo by Scott Reilly
Happy coding!
() Joost van der Schee
