Skip to main content
Overview

Introduction

Scrollspy is a Bootstrap component that automatically updates navigation links based on the user's scroll position within a page or scrollable container. As the user scrolls, the corresponding nav link gets the .active class applied to it.

This is especially useful for long documentation pages, single-page layouts, or any content that benefits from contextual navigation. No custom JavaScript is required — Bootstrap handles everything declaratively via data attributes.

Install

Setup

Add data-bs-spy="scroll" to the scrollable element (often <body> or a scrollable <div>). Point data-bs-target at the selector for your nav. Add tabindex="0" when the spy target is not <body>.

<!-- On <body> (whole-page scroll) -->
<body
  data-bs-spy="scroll"
  data-bs-target="#myNav"
  data-bs-offset="80"
>

<!-- On a scrollable div -->
<div
  data-bs-spy="scroll"
  data-bs-target="#myNav"
  data-bs-offset="0"
  tabindex="0"
  style="height: 400px; overflow-y: scroll;"
>
  ...
</div>
How it works

Usage

Each nav link's href must match the id of a section inside the scrollable container. Bootstrap monitors the scroll position and adds .active to the matching link automatically.

<!-- Nav -->
<nav id="myNav">
  <ul class="nav">
    <li><a class="nav-link" href="#section1">Section 1</a></li>
    <li><a class="nav-link" href="#section2">Section 2</a></li>
    <li><a class="nav-link" href="#section3">Section 3</a></li>
  </ul>
</nav>

<!-- Sections -->
<div id="section1">Content for section 1</div>
<div id="section2">Content for section 2</div>
<div id="section3">Content for section 3</div>

Bootstrap applies .active to the nav link as soon as the corresponding section reaches the offset threshold from the top of the scroll container.

Config

Options

Scrollspy can be configured via data attributes or JavaScript:

// Via JavaScript
const scrollSpy = new bootstrap.ScrollSpy(document.body, {
  target: '#myNav',
  offset: 100,    // px from top before section activates (default: 10)
  method: 'auto'  // 'auto' | 'offset' | 'position'
})

offset — Number of pixels to offset from top when calculating the active section.
methodoffset uses getBoundingClientRect(); position uses offsetTop/offsetLeft; auto picks based on context.

Events

Events

Bootstrap fires activate.bs.scrollspy on the scroll element every time a new nav item becomes active. Use event.relatedTarget to get the newly activated link element.

const scrollEl = document.querySelector('[data-bs-spy="scroll"]')

scrollEl.addEventListener('activate.bs.scrollspy', function (event) {
  console.log('Active target:', event.relatedTarget)
  // event.relatedTarget → the newly active <a> element
})

Live event log (scroll to see it fire):

→ Waiting for scroll events...
Advanced

Refresh

If you dynamically add or remove sections after the page loads, call .refresh() to recalculate all section offsets. Without a refresh, newly added sections won't be tracked.

// Get the ScrollSpy instance and refresh it
const instance = bootstrap.ScrollSpy.getInstance(
  document.querySelector('[data-bs-spy="scroll"]')
)
instance.refresh()

// Or via jQuery-style chaining:
// bootstrap.ScrollSpy.getOrCreateInstance(el).refresh()

You should also call refresh() if the container's height changes (e.g. after an accordion expands), since Bootstrap calculates section thresholds based on element positions at initialization time.

Tip: When using a fixed or sticky navbar, set data-bs-offset to the navbar's height (e.g. data-bs-offset="56") so sections activate at the right moment — not while hidden behind the bar.

CINCINNATI PLAYHOUSE
IN THE PARK
962 Mt. Adams Circle,
Cincinnati, OH 45202

M: 12 p.m. – 5 p.m.
Tu - Sa: 12 p.m. – 8 p.m.
Su: 12 p.m. – 2:30 p.m.

On non-performance days, the Box Office closes at 5 p.m.

BOX OFFICE
513-421-3888

TO DONATE
513-977-2021

ADMINISTRATIVE OFFICE
513-345-2242

ArtsWaveThe Shubert Foundation IncOhio Arts Council
tony award
COPYRIGHT © 2023 CINCINNATI PLAYHOUSE IN THE PARK. ALL RIGHTS RESERVED.