I’m trying converting all images to webp format and resizing them to a maximum width of 600px. I would like to keep the original size if the image is already less than 600px wide. Markdown posts still use original images (bundle resources).
Can anyone share a code snippet with me so it can do it automatically, such as an img tag with a webp file and lazy load?
Thanks, it would be images in bundle content posts.
Assuming you add those images to a page using Markdown image links, you’ll need to implement an image render hook based on Hugo’s embedded image render hook.
Here’s a variation of the image render template I’ve been using, with some adjustments.
- If you’re not using the extended version of Hugo, then images will be resized but not converted to WEBP.
- Although it is possible with Hugo, remote resources won’t be resized or converted by the following code. This can be resource heavy and time consuming if not used with caution.
- GIF images won’t be converted as the library Hugo uses cannot yet handle animated GIFs. Remove the respective condition if that’s not an issue.
- Local SVG images will be embedded within the HTML output, which is opinionated but in my use case permits coloring them with CSS. We’re assuming they contain safe HTML.
<!-- layouts/partials/render-image.html -->
<!-- get image URL from Markdown tag -->
{{- $src := (.Destination | safeURL) -}}
{{ $src = replace $src "./" "" }}
<!-- check .Store.Get "imgwidth" or use default width -->
{{- $imgwidth := .Page.Store.Get "imgwidth" | default 600 -}}
<!-- check if it exists as a page resource -->
{{- with (or ((.Page.Resources.ByType "image").Get $src) ((resources.ByType "image").Get $src)) -}}
<!-- if SVG then output its contents -->
{{- if strings.HasSuffix $src ".svg" -}}
{{ .Content | safeHTML }}
{{- else -}}
{{ $resized := . }}
<!-- resize if wider than "imgwidth" but if GIF file then avoid resizing animations; WebP animations not yet supported; see upstream ticket: https://github.com/golang/go/issues/53364 -->
{{ if and (gt .Width $imgwidth) (ne .MediaType.SubType "gif") }}
{{ if hugo.IsExtended }}
{{- $resized = .Resize (print $imgwidth "x webp") -}}
{{ else }}
{{- $resized = .Resize (print $imgwidth "x") -}}
{{ warnf "Missing Hugo Extended, in partial render-image.html" }}
{{ end }}
{{ end }}
<img src="{{ $resized.RelPermalink }}"
width="{{ $resized.Width }}"
height="{{ $resized.Height }}"
{{ with $.PlainText }} alt="{{ . }}" {{ end }}
{{ with $.Title }} title="{{ . | plainify | htmlEscape }}" {{ end }}
{{- range $k, $v := $.Attributes -}}
{{- if $v -}}
{{- printf " %s=%q" $k ($v | htmlEscape) | safeHTMLAttr -}}
{{- end -}}
{{- end -}}
loading="lazy" decoding="async" />
<!-- closing tag on img intented, for compatibility with XML output -->
{{- end -}}
{{- else -}}
<!-- or otherwise its an external resource so load the URL -->
<img src="{{ .Destination | safeURL }}"
{{ with $.PlainText }} alt="{{ . }}" {{ end }}
{{ with $.Title }} title="{{ . | plainify | htmlEscape }}" {{ end }}
{{- range $k, $v := .Attributes -}}
{{- if $v -}}
{{- printf " %s=%q" $k ($v | htmlEscape) | safeHTMLAttr -}}
{{- end -}}
{{- end -}}
loading="lazy" decoding="async" data-src="external" />
{{- end -}}
I hope that helps. Notes to improve any of the above, welcome!