Okay, let me see if I can explain this clearly.
I had a guy build me a basic Hugo theme because I’m bad at design. One of the cool features of his theme is that it uses a little CSS wizardry to make full-width images using the markdown image tag by appending #wide
to the image URL:
![An image of my cat that's full-width](/images/my-cat.jpg#wide)
This is accomplished in his CSS like this:
img[src$='#wide'] {
display: block;
width: 100vw;
max-width: none;
margin-left: 50%;
transform: translateX(-50%);
border-radius: 0;
}
Here’s the thing, though: I want to use Hugo’s built in image processing features. But Hugo gets confused if I have #wide
in the end of file names.
So to solve this problem, I have to hook in to the markdown engine via a file in /layouts/_default/_markup/
So the first thing I do is add the file render-image.html
into that folder, with this content:
{{ $src := (resources.Get .Destination) }}
{{ $alt := .PlainText | safeHTML }}
{{ if $src }}
{{ $tinyw := default "500x webp" }}
{{ $smallw := default "800x webp" }}
{{ $mediumw := default "1200x webp" }}
{{ $largew := default "1500x webp" }}
{{ $data := newScratch }}
{{ $data.Set "tiny" ($src.Resize $tinyw) }}
{{ $data.Set "small" ($src.Resize $smallw) }}
{{ $data.Set "medium" ($src.Resize $mediumw) }}
{{ $data.Set "large" ($src.Resize $largew) }}
{{ $tiny := $data.Get "tiny" }}
{{ $small := $data.Get "small" }}
{{ $medium := $data.Get "medium" }}
{{ $large := $data.Get "large" }}
<picture>
<source media="(max-width: 376px)"
srcset="{{with $tiny.RelPermalink }}{{.}}{{ end }}">
<source media="(max-width: 992px)"
srcset="{{with $small.RelPermalink }}{{.}}{{ end }}">
<source media="(max-width: 1400px)"
srcset="{{with $medium.RelPermalink }}{{.}}{{ end }}">
<source media="(min-width: 1600px)"
srcset="{{with $large.RelPermalink }}{{.}}{{ end }}">
<img alt="{{ $alt }}" loading="lazy" title="{{ $alt }}"
src="{{ $src }}" height="{{ $src.Height}}" width="{{ $src.Width }}">
</picture>
{{ else }}
<code>ERR: IMAGE RESOUCE FAILED TO MOUNT TO HUGO</code>
{{ end }}
I forget where I got this code (maybe Hugo docs!), but it is really great because it takes the image as a resource, resizes it a few times, converts to webp, and outputs the tag as a <picture>
tag instead of an <img>
tag. Very nifty.
The problem with this, though, is that I can’t take advantage of my guy’s super cool CSS trick for full-size images in markdown! If I have #wide
on my images Hugo won’t be able to find them. It will look for a file that is literally called /images/somefile.jpg#wide
.
So to fix the problem I use in
and substr
to look for and remove #wide
, and then readd it later with printf
.
So first I make a $destination
variable to handle that search and remove of the #wide
parameter:
{{ $destination := "" }}
Next, I search for #wide
using in
and then, if present, remove it with substr
:
{{ if in .Destination "#wide" }}
{{ $destination = (substr .Destination 0 -5) }}
{{ else }}
{{ $destination = .Destination }}
{{ end }}
Then, I use my newly made $destination
variable in place of .Destination
in the original code:
{{ $src := (resources.Get $destination) }}
The rest of the code continues as normal until I need to output the image. At that point, I just re-run my if
conditional to check for #wide
again, and if it’s present, I append with printf
:
<img alt="{{ $alt }}" loading="lazy" title="{{ $alt }}"
src="
{{- if in .Destination "#wide" -}}
{{- printf "%s#wide" $src -}}
{{- else -}}
{{- $src -}}
{{- end -}}" height="{{- $src.Height -}}" width="{{- $src.Width -}}">
It works like a charm!
The end result is I can still use markdown image commands, and even put #wide
on the end of the filename and everything works like it should, except now it also takes advantage of Hugo’s image processing!
Let me know what you think, or if you know a cleaner way to achieve this!