How to move a <style> block generated in a shortcode to the HTML head?

I’ve developed custom footnote shortcodes which add CSS styling based on the reference elements’ ID attributes. In other words, it’s not possible to “foresee” the IDs and to write the CSS statically (in advance); it must be done dynamically inside the shortcodes.

While the styling produces the design I intended, I noticed that the <style> element is not actually permitted in the <body> when viewing the generated HTML source code in Firefox, but is only allowed in the <head>. Didn’t know that!

In order to keep my HTML valid, I looked for

  • HTML workarounds like slapping the scope attribute onto the <style> element but that’s deprecated,
  • Hugo workarounds to move the <style> element to the <head> somehow but couldn’t find anything.

Naturally, a template at the top of the page (like my head.html partial) will be executed earlier than a template at the bottom (like my footnotelist.html shortcode), so the head partial won’t be able to read .Page.Store variables set by the footnote shortcode.

ChatGPT recommended me to do this:

{{ $content := .Content }}

<!DOCTYPE html>
<html>
  <head>
    {{ partial "head.html" . }}
  </head>
  <body>
    {{ $content }}
  </body>
</html>

Is that good practice? Or should I just accept the syntax error? Or do something else entirely?

Only after having posted my question, Discourse finally decided to show me several existing threads discussing the same problem, one of which I decided to follow: How to associate CSS to a specific partial and render it in <head> section of the HTML

Based on this, I implemented the following solution using templates.Defer:

head.html partial:

<head>
	{{- $data := (dict "page" .Page ) -}}

	{{- with (templates.Defer (dict "data" $data)) -}}
		{{ with .page.Store.Get "additionalStyles" }}
			<style>
				{{- range . -}}
					{{ . | safeCSS }}
				{{- end -}}
			</style>
		{{- end -}}
	{{- end -}}
</head>

footlist.html shortcode:

{{ .Page.Store.Add "additionalStyles" (partial "footnote-style" (dict "relevant" "data") | safeCSS) }}

footnote-style.css is a CSS partial which uses the variables from the given dictionary.

1 Like

I am glad that opening this old thread of mine you mentioned helped you! The implementation you suggest is great, but from my experience I found that using a <link rel="stylesheet "> tag with href attribute equal to an asset in the assets directory works even better as the css is stored in a separate .css file (not written inline and passed as data to a partial)…

PS: For shortcodes I think there is another choice, designed for such use cases as yours: HasShortcode

1 Like