tl;dr
You can use the {{- "" -}} template syntax to remove trailing whitespace on links in Hugo.

For some reason, Hugo was rendering links with a space after them. Here’s a screenshot of what that looked like:

Link generated by Hugo with a space after it for some reason.

It’s subtle but becomes more obvious and distracting in link-heavy pages.

Here is the markdown that I was using to generate the link above. Nothing out of the ordinary:

1
This sentence has a [link at the end](https://example.com).

In Hugo, you can apply post-processing to links through link render hooks by editing the layouts/_default/_markup/render-link.html file. Here’s my terrible template that I use to process links. Once again, nothing stood out that would add unnecessary whitespace after links:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{{- $url := .Destination -}}
{{- $refParam := "" -}}
{{- $refDomain:= "" -}}
{{- $hasQuery := strings.Contains $url "?" -}}
{{- $hasHash := strings.Contains $url "#" -}}
{{- if $hasQuery -}}
    {{/*  taking into account existing query strings  */}}
    {{- $refParam = "&ref=" -}}
    {{- $refDomain = "nelson.cloud" -}}
{{- else if $hasHash -}}
    {{/*  ensuring that URL doesn't have a hash #  */}}
    {{/*  do nothing in this case  */}}
{{- else -}}
    {{- $refParam = "?ref=" -}}
    {{- $refDomain = "nelson.cloud" -}}
{{- end -}}

<a href="{{ .Destination | safeURL }}{{ $refParam }}{{ $refDomain }}"{{ with .Title}} title="{{ . }}"{{ end }}{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener noreferrer"{{ end }}>{{ .Text | safeHTML }}</a>

Here is the HTML that was generated by Hugo based on the Markdown I wrote and the processing in render-link.html. This is straight from the browser dev tools:

HTML of the link generated by Hugo before the template syntax was added.

The period was on its own line, which looks suspicious. Why is there additional space being added though? I tried modifying my CSS, my Markdown, and render-link.html to see if I could remove the whitespace but nothing worked.

Eventually, I was out of ideas and asked ChatGPT what could be going wrong. ChatGPT suggested I could add the {{- "" -}} template syntax to render-link.html to remove the whitespace. Apparently that would force the removal of both leading and trailing whitespace. And sure enough it worked!

I modified my render-link.html template to include the {{- "" -}} template syntax at the end of the <a> tag in the highlighted line:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{{- $url := .Destination -}}
{{- $refParam := "" -}}
{{- $refDomain:= "" -}}
{{- $hasQuery := strings.Contains $url "?" -}}
{{- $hasHash := strings.Contains $url "#" -}}
{{- if $hasQuery -}}
    {{/*  taking into account existing query strings  */}}
    {{- $refParam = "&ref=" -}}
    {{- $refDomain = "nelson.cloud" -}}
{{- else if $hasHash -}}
    {{/*  ensuring that URL doesn't have a hash #  */}}
    {{/*  do nothing in this case  */}}
{{- else -}}
    {{- $refParam = "?ref=" -}}
    {{- $refDomain = "nelson.cloud" -}}
{{- end -}}

<a href="{{ .Destination | safeURL }}{{ $refParam }}{{ $refDomain }}"{{ with .Title}} title="{{ . }}"{{ end }}{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener noreferrer"{{ end }}>{{ .Text | safeHTML }}</a>{{- "" -}}

Then my links were rendering without additional space after them, and here’s a screenshot showing that:

Link generated by Hugo with the space after it gone now.

The weird thing is that when I checked the HTML being generated, it looked identical to the original before I added the template syntax and I had no idea why:

HTML of the link generated by Hugo after the template syntax was added.

But at least the whitespace was gone when viewing the article in a browser. That’s what matters.

This template syntax trick can probably be applied to other areas of Hugo and not just for links, but I haven’t done any additional experimenting.

References

  • Wherever ChatGPT stole got this information from. I feel weird using ChatGPT as a reference but that really is how I discovered the solution.