Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • B bootstrap
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 263
    • Issues 263
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 114
    • Merge requests 114
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Bootstrap
  • bootstrap
  • Issues
  • #34381
Closed
Open
Issue created Jun 30, 2021 by Administrator@rootContributor

Scrollspy does not handle all valid HTML5 element ids

Created by: chrisyeh96

Bug Report

Scrollspy stops working when any of the DOM elements it is "spying" on has an id that starts with a number, such as

<div id="3rd">Text</div>

This should be considered a bug because HTML5 has no restrictions on what form an ID can take (official spec).

There are no other restrictions on what form an ID can take; in particular, IDs can consist of just digits, start with a digit, start with an underscore, consist of just punctuation, etc.

Historically, HTML4 did not allow for ids to start with numbers, but it would seem ridiculous to assume only HTML4 content today.

Bug Demo

See this JSBin for the demo. https://jsbin.com/rehematazo/3/edit?html,output. By default, I've commented out the <a> elements that link to <div>s whose IDs start with a digit, so Scrollspy works. But once you uncomment out these <a> tags, then Scrollspy stops working entirely.

I have also copied the HTML code for the demo here:

Code
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
  <style>
    .tall { height: 300px; }
    
    .toc-nav { /* <nav> */
      position: sticky;
      top: 0;
      height: min-content;
      max-height: 100vh;
      overflow-y: auto;
    }
    
    .toc-nav a.active {
      color: #007bff;
    }
  </style>
</head>
<body data-bs-spy="scroll" data-bs-target="#nav">

  <div class="container"><div class="row">

  <main class="col-8">
  <h2 id="A">ID A</h2>
  <div class="tall">Chunk of text</div>
  <h2 id="B">ID B</h2>
  <div class="tall">Chunk of text</div>
  <h2 id="C">ID C</h2>
  <div class="tall">Chunk of text</div>

  <h2 id="1">ID 1</h2>
  <div class="tall">Chunk of text</div>
  <h2 id="2">ID 2</h2>
  <div class="tall">Chunk of text</div>
  <h2 id="3">ID 3</h2>
  <div class="tall">Chunk of text</div>
  </main>
  
  <nav class="col-4 toc-nav" id="nav">
    <nav class="navbar navbar-light">
      <span class="navbar-brand">Contents</span>
      <a class="list-group-item list-group-item-action" href="#A">Item A</a>
      <a class="list-group-item list-group-item-action" href="#B">Item B</a>
      <a class="list-group-item list-group-item-action" href="#C">Item C</a>

      <!-- Uncomment the following 3 lines to see the bug:
           Once you uncomment, you will notice that Scrollspy stops working.
        -->
      <!-- <a class="list-group-item list-group-item-action" href="#1">Item 1</a>
      <a class="list-group-item list-group-item-action" href="#2">Item 2</a>
      <a class="list-group-item list-group-item-action" href="#3">Item 3</a> -->
    </nav>
  </nav>

  </div></div>

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
</body>
</html>

Why this happens, and possible fixes

This bug seems to happen because Bootstrap uses document.querySelector() to identify elements:

https://github.com/twbs/bootstrap/blob/696996dd4f5b7319413655b9134ca2f3768c2549/js/dist/scrollspy.js#L78

However, document.querySelector() only works for valid CSS selector strings, and CSS selector strings for IDs cannot start with a number (even though HTML IDs can). See this StackOverflow Q&A for more info: https://stackoverflow.com/q/20306204. This causes Bootstrap JS to encounter the following error (copied from Microsoft Edge console):

Uncaught DOMException: Failed to execute 'querySelector' on 'Document': '#3rd' is not a valid selector.
    at <anonymous>:1:10

The StackOverflow Q&A proposes several possible fixes. For example, document.getElementById("3rd") works fine, but only works with ID-based selectors. I am also not sure which fixes fall within Bootstrap's browser compatibility goals.

System Info

OS: Windows 10 20H1 Browser: Microsoft Edge (Chromium) 91.0.864.59 and Firefox 89.0.2 (64-bit) Bootstrap version 5.0.2

Assignee
Assign to
Time tracking