Auto ID generation partially incompatible with allowable CSS selectors

I’m using the following setting to generate IDs for headings:

    [markup.goldmark.parser]
        autoHeadingID = true
        autoHeadingIDType = "github"

Most are certainly aware of this setting, but it has a major backdraw: If one has a heading starting wit a digit, the generated ID will itself start with one. While this is perfectly valid on the HTML side, it is quite an inconvenience when working with CSS selectors. Those can work, but need to be escaped, is there a way to prepend an ID with some default, like id_?

More on the CSS ID issue in this Stackoverflow answer.

You may use a heading render hook to add a prefix:

Used of _here , but you may conditionally add it, define as site parameter …

layouts/_markup/render-heading.html
<h{{ .Level }} id="_{{ .Anchor }}" {{- with .Attributes.class }} class="{{ . }}" {{- end }}>
  {{- .Text -}}
</h{{ .Level }}>

when generating headings in your layouts, use urls.Anchorize

<h1 id="{{ add "_" (site.Title | urls.Anchorize) }}">{{ site.Title }}</h1>

Altering the id attribute in a heading render hook will break tables of content (e.g., Page.TableOfContents). See Issue 8383, which I suspect will not or cannot be addressed (:chicken: :egg:).

Instead, use a Markdown attribute to override the id as needed. For example:

## 1 The first heading {#foo}

Which is rendered to:

<h2 id="foo">1 The first heading</h2>

Changing the way we auto-generate id attributes has been discussed here:
https://github.com/gohugoio/hugo/issues/8997

3 Likes