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
| Attribute | Goes on | Purpose |
|---|---|---|
data-spy="scroll" | The scrollable container (often <body>) | Turns on scroll watching for that element |
data-target | Same container | Points to the nav (by selector) whose links get highlighted |
data-offset | Same container | Pixels 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>
$('[data-spy="scroll"]').scrollspy('refresh') so the plugin recalculates its section offsets.