blog hoarding cv now note

Hugo With Lazy Loading and Webp






by Fundor 333

Reading time 4 minutes
Word count 736
2021-07-27 10:00:00



New work and new knowledge. For having a better site/blog performance you can use loadding=“static” in the resources you need last and, if there are img, you can use avif and webp for faster render page time.

So I need to implement into my personal Hugo’s blog.

Hugo problem

In Hugo you can edit the themplate for having all the “fix” img with lazy-loading or img alternative but if there are image inside a _.Content_of a post or other type you can’t edit them in a easy way. So I search online and found about the _/layouts/_default/markup/render-image.html 1.

A simple render-image

Render-image is an override of the default markdown to HTML with your custom code. So I search for some example and this is the simple one:

<img loading="lazy" src="{{ .Destination | safeURL }}" alt="{{ .Text }}" {{ with .Title}} title="{{ . }}" {{ end }} />

So from

![Random img](cat.jpg)

we have

<img loading="lazy" src="cat.jpg" alt="Random img">

With only one line of code all the img inside a .Content has an alt filled and a loading=“lazy”.

After this I want to add to all img the width and the height of the image and, if present, add the WebP and/or AVIF for optimization (I suggest some article for more info 2 3 4 5 )

Problems with Hugo’s Statics File and Hugo’s Page Bundles

I find some article about WebP and Hugo but there are some problems. All the word who implement a solution for this problem has a blog without the Page Bundles .

So I decide to choose one and “update” the solution for the Page Bundles. And my bas was this post: WebP and AVIF images on a Hugo website .

The code

So this is my final render-image.html.

{{- $src := ( .Destination | safeURL ) -}}
{{- if strings.HasPrefix $src "http" -}}
<img loading="lazy" src="{{ .Destination | safeURL }}" alt="{{ .Text }}" {{ with .Title}} title="{{ . }}" {{ end }} />
{{- else -}}
<picture>
  {{ $isJPG := eq (path.Ext .Destination) ".jpg" }}
  {{ $isPNG := eq (path.Ext .Destination) ".png" }}

  {{ if ($isJPG) -}}
  {{ $avifPath:= replace .Destination ".jpg" ".avif" }}
  {{ $avifPathStatic:= (add (add "/content/" .Page.Dir)  $avifPath) }}

  {{ if (fileExists $avifPathStatic) -}}
  <source srcset="{{ $avifPath | safeURL }}" type="image/avif">
  {{- end }}

  {{ $webpPath:= replace .Destination ".jpg" ".webp" }}
  {{ $webpPathStatic:= (add (add "/content/" .Page.Dir)  $webpPath )}}

  {{ if (fileExists $webpPathStatic) -}}
  <source srcset="{{ $webpPath | safeURL }}" type="image/webp">
  {{- end }}
  {{- end }}

  {{ if ($isPNG) -}}
  {{ $avifPath:= replace .Destination ".png" ".avif" }}
  {{ $avifPathStatic:= (add (add "/content/" .Page.Dir)  $avifPath )}}

  {{ if (fileExists $avifPathStatic) -}}
  <source srcset="{{ $avifPath | safeURL }}" type="image/avif">
  {{- end }}

  {{ $webpPath:= replace .Destination ".png" ".webp" }}
  {{ $webpPathStatic:= (add (add "/content/" .Page.Dir)  $webpPath )}}

  {{ if (fileExists $webpPathStatic) -}}
  <source srcset="{{ $webpPath | safeURL }}" type="image/webp">
  {{- end }}
  {{- end }}

  {{ $img := imageConfig (add (add "/content/" .Page.Dir)  .Destination) }}

  <img src="{{ .Destination | safeURL }}" alt="{{ .Text }}" loading="lazy" decoding="async" width="{{ $img.Width }}" height="{{ $img.Height }}" />
</picture>
{{- end -}}

The start if is for manage linked image and work as a base case of this code using the “simple” code for the base. For the “this is one of my blog’s image” case we use a picture tag. All the source tags after are use only if ugo find the img with the correct img format.

But the real different form the pawelgrzybek’s code. I get the image config form the image in the content and not from the static’s path. With the config of the image we can get the width and the height of the img.

That’s all?

The only problem now is to make the WebP and the AVIF file from your image and pawelgrzybek suggest this example for compressing the img:

cwebp cat.jpg -o cat.webp
avifenc --min 10 --max 30 cat.jpg cat.avif

If you are a macOs user you can use Homebrew .

brew install webp
brew install joedrago/repo/avifenc

If you add webp and avifenc to your build script like a makefile and integrate into your CI or your workflow.

If you need help or have some suggestion you can comment or tweet me


  1. From Hugo’s Docs  ↩︎

  2. Comparing AVIF vs WebP file sizes at the same DSSIM  ↩︎

  3. On the hunt for the best image quality per byte  ↩︎

  4. AVIF support  ↩︎

  5. WebP Compression Study  ↩︎

If you liked this article,

please share it on

or webmention it