๐Ÿ“‘ Chapter 6: Headings & Paragraphs

Creating a Table of Contents with Headings

Build automated, accessible Table of Contents (TOC) generators using JavaScript DOM traversal, fragment identifiers, and CSS `scroll-margin-top` offset mechanics.

LEARNING OBJECTIVES โŒต
  • Implement manual and automated client-side Table of Contents (TOC) systems using semantic HTML lists (<ol>, <ul>) and fragment identifier links (<a href="#id">).
  • Write a clean, zero-dependency JavaScript algorithm that queries the DOM heading tree, generates URL-safe slug identifiers, and renders a nested TOC structure.
  • Solve the classic sticky header overlap bug using modern CSS scroll-margin-top on heading targets.
  • Integrate CSS scroll-behavior: smooth while honoring user accessibility preferences via prefers-reduced-motion.
๐ŸŽฌ INTERACTIVE VISUAL PIPELINE Core Architecture Simulation
๐ŸŒ
1. Input
Directives & Tags
โš™๏ธ
2. Parse
Tokenizer & AST
๐ŸŒณ
3. Layout
Box Model & Flow
๐ŸŽจ
4. Render
GPU Paint & Composite
PHASE 1: INPUT & DIRECTIVES
Browser receives declarative markup stream, parsing tag tokens and initializing component state.

๐Ÿ“– The Mental Model & Story (Intuitive Foundation)

Imagine hiking on a multi-day mountain trail. At the trailhead sits a large wooden map displaying all the major peaks, campsites, and water stations, each marked with a precise trail marker code:
[Peak 1: Eagle Rock - Mile 4], [Peak 2: Bear Ridge - Mile 9].

Along the trail itself, every campsite and summit has a matching wooden signpost embedded into the dirt with that exact code.

Trailhead Map (Table of Contents):         Trail Signposts (DOM Headings):
+------------------------------------+    +------------------------------------+
| ๐Ÿ“ Eagle Rock (#eagle-rock)        | โ”€โ”€โ–บ| <h2 id="eagle-rock">Eagle Rock</h2>|
| ๐Ÿ“ Bear Ridge (#bear-ridge)        | โ”€โ”€โ–บ| <h2 id="bear-ridge">Bear Ridge</h2>|
| ๐Ÿ“ Summit Camp (#summit-camp)      | โ”€โ”€โ–บ| <h2 id="summit-camp">Summit...</h2>|
+------------------------------------+    +------------------------------------+

In web architecture, a Table of Contents is that trailhead map. It provides quick navigational shortcuts.

  • The Trailhead Map is an accessible <nav> containing anchor links (<a href="#slug">).
  • The Trail Signposts are your semantic headings (<h2>, <h3>) equipped with matching id="slug" attributes.

When a user clicks a TOC link, the browser viewport instantly scrolls directly to the corresponding heading signpost.


Technical Deep Dive & Specifications

Fragment Identifiers & Anchor Navigation

In RFC 3986, the portion of a URL following the hash symbol (#) is the fragment identifier. When navigating to https://example.com/guide#caching-strategies:

  1. The browser parses the fragment caching-strategies.
  2. It executes an internal DOM query: document.getElementById('caching-strategies').
  3. It scrolls the element into view and updates the browser history stack.
                               URL: https://example.com/guide#performance
                                                                   โ”‚
                                                                   โ–ผ
+โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€+
| <nav aria-label="Table of Contents">                                            |
|   <ol>                                                                          |
|     <li><a href="#performance">Performance Optimization</a></li> โ”€โ”€โ”€โ”€โ”€โ”€โ”        |
|   </ol>                                                                โ”‚        |
| </nav>                                                                 โ”‚        |
|                                                                        โ”‚        |
| ... Content ...                                                        โ”‚        |
|                                                                        โ–ผ        |
| <h2 id="performance">Performance Optimization</h2> โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        |
| <p>Passage content explaining memory and CPU optimization...</p>                |
+โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€+

The Sticky Header Overlap Bug & scroll-margin-top

When a website features a position: fixed or position: sticky top navigation bar (e.g., height 70px), standard browser fragment scrolling positions the target heading at the absolute top of the viewport (Y = 0), directly underneath the sticky header!

THE STICKY HEADER BUG:                    THE scroll-margin-top FIX:
+-------------------------------+         +-------------------------------+
| [ FIXED HEADER (70px) ]       |         | [ FIXED HEADER (70px) ]       |
| ----------------------------- |         | ----------------------------- |
| H2 IS HIDDEN UNDER HEADER! โŒ |         |                               |
| <p>Paragraph text begins...</p>|         | <h2 id="...">Heading</h2>  โœ… |
+-------------------------------+         | <p>Paragraph text begins...</p>|
                                          +-------------------------------+

The Modern CSS Solution:

Apply scroll-margin-top to all headings with id attributes:

/* Offset target scroll position to account for fixed navbar */
h2[id], h3[id], h4[id] {
  scroll-margin-top: 5rem; /* 80px buffer above heading */
}

Automated Dynamic TOC Generation Algorithm

Instead of manually typing and synchronizing id attributes and <a href="#..."> links across hundreds of documentation pages, modern engineering teams write automated JavaScript scrapers:

Automated TOC Algorithm:
1. Select Target: const headings = document.querySelectorAll('main h2, main h3');
2. Iterate: For each heading element:
     a. Extract clean text content.
     b. Generate URL-safe slug (e.g., "1.1 Cache Control" โ”€โ”€โ–บ "cache-control").
     c. Assign heading.id = slug (if not already set).
     d. Create <li><a href="#slug">Heading Text</a></li>.
     e. If h3, nest inside child <ol>; if h2, append to root <ol>.
3. Mount: Append compiled <ol> tree into <nav aria-label="Table of contents">.

๐Ÿ’ป Interactive Code Playground

Starter Code

Line-by-Line Code Breakdown

  • Lines 10โ€“17 (scroll-behavior: smooth & @media (prefers-reduced-motion)): Enables smooth gliding animations when clicking TOC anchors while instantly disabling it for vestibular-sensitive users.
  • Lines 23โ€“35 (.site-nav { position: fixed; height: 60px; }): Emulates an enterprise fixed top navigation bar.
  • Lines 63โ€“65 (h2[id], h3[id] { scroll-margin-top: 75px; }): The critical CSS property that stops the scrolled heading 75px below the viewport top, completely preventing header overlap.
  • Lines 114โ€“121 (document.querySelectorAll('h2, h3')): Queries the content container for all relevant headings in document order.
  • Lines 128โ€“134 (slug generation): Converts strings like "1.1 Write-Through Caching" into URL-safe hash targets ("1-1-write-through-caching").
  • Lines 142โ€“153 (hierarchical nesting): Detects heading rank and automatically creates nested <ul> sublists inside <h2> list items.

Expected Browser Render Output


SYS: ACTIVE
HULL: 98%
CORE: STABLE
NET: ONLINE
HTML STARSHIP CODE TERMINAL playground.html
LIVE RENDER & DIAGNOSTICS CORE TEMP: 45ยฐC
INSPECTING DOM: VALID
TAGS: SCANNING...
[ FIXED HEADER: Cloud Architecture Docs (60px) ]

ON THIS PAGE (Sticky Sidebar)             Distributed Cache Topology
1. 1. Cache Invalidation Patterns         Architecting resilient memory caching tiers...
   โ€ข 1.1 Write-Through Caching
   โ€ข 1.2 Cache-Aside (Lazy Loading)       1. Cache Invalidation Patterns
2. 2. Replication and Sharding            Cache invalidation is notoriously challenging...
   โ€ข 2.1 Hash Ring Slot Distribution        1.1 Write-Through Caching
3. 3. Eviction Policies                     Data is written simultaneously to cache...

๐Ÿ‹๏ธ Hands-On Exercise

๐ŸŽฏ The Challenge: Build an Accessible Manual TOC with Scroll Offsets

You are building an offline documentation page. The page has a fixed 70px navigation bar. When clicking anchor links, the target headings are cut off by the header.

Instructions:

  1. Create an accessible <nav aria-label="Table of Contents"> containing an ordered list (<ol>) of links pointing to the #section-1, #section-2, and #section-3 IDs.
  2. Add unique id attributes to all <h2> headings.
  3. Fix the sticky header overlap bug using CSS scroll-margin-top.
  4. Add smooth scrolling with a prefers-reduced-motion safety guard.

๐Ÿ Starter Code Sandbox

SYS: ACTIVE
HULL: 98%
CORE: STABLE
NET: ONLINE
STARTER CODE SANDBOX exercise.html
LIVE RENDER & DIAGNOSTICS CORE TEMP: 45ยฐC
INSPECTING DOM: VALID
TAGS: SCANNING...

โš ๏ธ Common Pitfalls

  1. Duplicate or Malformed id Attributes: Having multiple headings with id="overview". IDs must be strictly unique within the DOM; duplicate IDs break fragment identifier jumping.
  2. Using Non-URL Safe Characters in Slugs: Generating IDs with spaces or punctuation (e.g., id="1.1 What's Next?"). Always normalize slugs with regex to lowercase alphanumeric hyphenated strings (id="1-1-whats-next").
  3. Padding Top Hacks on Headings: Adding padding-top: 80px; margin-top: -80px; to offset fixed headers. This legacy hack disrupts background colors, borders, and text selection. Use modern scroll-margin-top instead.
  4. Missing aria-label on <nav>: Creating multiple <nav> elements without labels. Screen reader users cannot tell the difference between the main site navigation and the table of contents.

๐Ÿ’ก Pro Tips

  1. IntersectionObserver ScrollSpy: Combine your dynamic TOC with an IntersectionObserver to automatically highlight the active heading in the sidebar as the user scrolls through the document.
  2. Deep-Linking Click-to-Copy Anchors: Inject an interactive # anchor button next to every heading (like GitHub and MDN docs) so users can click to copy direct fragment links to their clipboard.

๐Ÿ“Œ Key Takeaways

  • A Table of Contents pairs an accessible <nav> ordered list with heading fragment identifiers (#slug).
  • CSS scroll-margin-top is the modern standard solution to prevent sticky/fixed headers from obscuring target headings.
  • Client-side JavaScript algorithms can dynamically parse h2 and h3 tags, auto-generate slugs, and render nested TOC trees.
  • Always wrap smooth scrolling inside @media (prefers-reduced-motion: no-preference) to respect vestibular accessibility needs.
  • Ensure all heading id attributes are unique and sanitized into URL-safe slugs.
  • --
โญ LEARN: HTML ๐ŸŒŸ โš”๏ธ QUIZ BATTLE ARENA // ACTIVE
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 1 / 3

What CSS property natively resolves the issue where a fixed 60px header covers a heading when navigating via a #fragment anchor link?

Question 1 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 2 / 3

Why should an automated TOC generator sanitize heading text into a slug (e.g., converting "2.0: CI/CD & Deployments" to "2-0-ci-cd-deployments") before setting the id attribute?

Question 2 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 3 / 3

When providing multiple <nav> elements on a single page (such as a top site navbar and a sidebar Table of Contents), what is required for WCAG accessibility compliance?

Question 3 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP