Skip to content

TOC scrolling results in runtime error when heading ID starts with a digit #2329

@chalin

Description

@chalin

For example, see https://deploy-preview-7104--opentelemetry.netlify.app/blog/2025/ai-agent-observability/:

Uncaught SyntaxError: Failed to execute 'querySelector' on 'Element': '#2025-year-of-ai-agents' is not a valid selector.
    at Object.findOne (main.js:742:46)
    at ScrollSpy._initializeTargetsAndObservables (main.js:5760:50)
    at ScrollSpy.refresh (main.js:5655:12)
    at new ScrollSpy (main.js:5639:12)
    at ScrollSpy.getOrCreateInstance (main.js:693:43)
    at main.js:5824:17
    at handler (main.js:350:17)

For a heading like this:

# 1. Introduction

Hugo/Goldmark generates:

<h1 id="1-introduction">1. Introduction</h1>

The Issue is that:

  • HTML5 allows IDs to start with digits: <h1 id="1-introduction"> is ok
  • CSS selectors do not: querySelector('#1-introduction') is invalid CSS

From the CSS 2.1 Specification on Identifiers spec:

"In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (); they cannot start with a digit, two hyphens, or a hyphen followed by a digit."

I'd say that this is an upstream bug (check if there are any open issues). Documenting it here for now.


Update: this is a known ScrollSpy issue. A first attempt was made to solve it, but the issue persists, see:

Others who have faced similar issues:

So the problem isn't limited to headings that start with a digit. It can happen for an heading with an ID that isn't a valid CSS selector. A solution is to call CSS.escape() to sanitize the ID before it is used as a selector. Note that I've only see ScrollSpy fail when a heading ID starts with a digit, not other cases. Here's an example of ScrollSpy failing due to a href that doesn't start with a digit: #2328 (comment). Though admittedly, ScrollSpy fell into a larger HTML element scope that it should have.


Tasks

Workaround experiments & cleanup:

Metadata

Metadata

Assignees

No one assigned

    Labels

    UXbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions