Scrollspy

Scrollspy watches a scrollable area and automatically adds .active to the nav link that matches whichever section is currently in view. It's built for long single-page documents — exactly the shape of a TrailMap trail-guide page with Overview, Difficulty, Directions, and Reviews sections stacked one after another.

The Three Attributes You Need

AttributeGoes onPurpose
data-spy="scroll"The scrollable container (often <body>)Turns on scroll watching for that element
data-targetSame containerPoints to the nav (by selector) whose links get highlighted
data-offsetSame containerPixels to subtract from the trigger point, e.g. to clear a fixed header

Each section being spied on needs a matching id, and each nav link points at that id with a href="#id" anchor.

TrailMap Example: A Trail Guide With a Sticky Side-Nav

The scroll container is <body>, the target is the sticky sidebar nav, and an offset of 70 keeps the highlight change from happening a moment too late under TrailMap's fixed top header:

<!-- TrailMap: body is the scrollspy container -->
<body data-spy="scroll" data-target="#trailGuideNav" data-offset="70">

  <nav id="trailGuideNav" class="nav nav-pills nav-stacked" style="position:sticky; top:80px;">
    <li><a href="#overview">Overview</a></li>
    <li><a href="#difficulty">Difficulty</a></li>
    <li><a href="#directions">Directions</a></li>
    <li><a href="#reviews">Reviews</a></li>
  </nav>

  <section id="overview"><h2>Overview</h2></section>
  <section id="difficulty"><h2>Difficulty</h2></section>
  <section id="directions"><h2>Directions</h2></section>
  <section id="reviews"><h2>Reviews</h2></section>

</body>

As the hiker scrolls from Overview down toward Reviews, Scrollspy toggles .active on the matching sidebar link automatically — no scroll event listener of your own required.

Spying On a Smaller Scrollable Element

The container doesn't have to be <body>. Any element with a fixed height and overflow-y: scroll can be spied on — useful for a scrollable panel rather than the whole page.

<div data-spy="scroll" data-target="#miniNav" style="height:300px; overflow-y:scroll; position:relative;">
  ...
</div>
Refreshing after DOM changes: if you add or remove sections after the page loads (e.g. via AJAX), call $('[data-spy="scroll"]').scrollspy('refresh') so the plugin recalculates its section offsets.
Up next: Tab makes the Nav Tabs and Pills you styled earlier actually switch content panes.