Bootstrap - Scrollspy



This chapter will discuss about Bootstrap scrollspy. Bootstrap scrollspy automatically targets the navigation bar contents as you scroll the page.

How it work

When the element with the id referred by the anchor's href is scrolled into view, scrollspy works with nav, list group, and also works with any anchor element in the current page. Here's how it's works.

  • In order to utilize scrollspy, you should have two thing i.e a navigation, list group or a simple set of links, along with scrollable container such as the <body> or a custom element with a specific height and overflow-y: scroll.

  • To the scrollspy container, add attributes data-bs-spy="scroll" and data-bs-target="#navId", where "navId" refers the unique id of the corresponding navigation. If the container does not have any focusable element, include tabindex="0" to guarantee keyboard accessibility.

  • When you scroll within the "spied" container, anchor links in the navigation will have an .active class added or removed. If the id targets of links cannot be resolved, they will be ignored. For example, a <a href="#home">home</a> should have a corresponding <div id="home"></div>.

  • In the non-visible elements section, only visible elements will be considered and targeted.

Navbar

Scroll below the navbar area to see active class change. Open the dropdown and see highlighted items.

Example

You can edit and try running this code using Edit & Run option.

  <!DOCTYPE html>
  <html lang="en">
  <head>
    <title>Bootstrap - Scrollspy</title>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
  </head>
  <body>
    <nav id="navbarFirstExample" class="navbar bg-body-tertiary px-3 mb-3">
      <a class="navbar-brand" href="#">Tutorialspoints</a>
      <ul class="nav nav-pills">
        <li class="nav-item">
          <a class="nav-link" href="#scrollspyFirstTitle">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#scrollspySecondTitle">Services</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#scrollspyThirdTitle">About us</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#scrollspyFourthTitle">Contact us</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#scrollspyFifthTitle">Features</a>
        </li>
      </ul>
    </nav>
    <div data-bs-spy="scroll" data-bs-target="#navbarFirstExample" data-bs-root-margin="0px 0px -40%" data-bs-smooth-scroll="true" class="scrollspy-example bg-body-tertiary p-3 rounded-2" tabindex="0">     
      <h4 id="scrollspyFirstTitle">Home</h4>
      <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group. Scrollspy works with nav and list group.</p>
      <h4 id="scrollspySecondTitle">Services</h4>
      <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
      <h4 id="scrollspyThirdTitle">About us</h4>
      <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group. Scrollspy works with nav and list group.</p>
      <h4 id="scrollspyFourthTitle">Contact us</h4>
      <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
      <h4 id="scrollspyFifthTitle">Features</h4>
      <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
     </div>
  </body>
  </html>

Nested nav

Scrollspy supports nested .navs and makes their parents .active when they are .active. See active class changes while scrolling the navbar.

Example

You can edit and try running this code using Edit & Run option.

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <title>Bootstrap - Scrollspy</title>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
      <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
    </head>
    <body>
      <div class="row mt-2">
        <div class="col-4">
          <nav id="nestatedNavbar" class="h-100 flex-column align-items-stretch pe-4 border-end">
            <nav class="nav nav-pills flex-column">
              <a class="nav-link" href="#home">Home</a>
              <nav class="nav nav-pills flex-column">
                <a class="nav-link ms-3 my-1" href="#login">Log in</a>
                <a class="nav-link ms-3 my-1" href="#logout">Log out</a>
              </nav>
              <a class="nav-link" href="#aboutus">About us</a>
              <a class="nav-link" href="#contactus">Contact Us</a>
            </nav>
          </nav>
        </div>
    
        <div class="col-8">
          <div data-bs-spy="scroll" data-bs-target="#nestatedNavbar" data-bs-smooth-scroll="true" class="bg-body-tertiary p-3 rounded-2 my-2" tabindex="0">
            <div id="home">
              <h4>Home</h4>
              <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
            </div>
            <div id="login">
              <h5>Log In</h5>
              <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group. Scrollspy works with nav and list group</p>
            </div>
            <div id="logout">
              <h5>Log out</h5>
              <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
            </div>
            <div id="aboutus">
              <h4>About us</h4>
              <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group. Scrollspy works with nav and list group</p>
            </div>
            <div id="contactus">
              <h4>Contact us</h4>
              <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
            </div>
          </div>
        </div>
      </div>
    </body>
    </html>

List group

Scrollspy supports .list-groups. See the active class change as you scroll near the list group.

Example

You can edit and try running this code using Edit & Run option.

  <!DOCTYPE html>
  <html lang="en">
  <head>
    <title>Bootstrap - Scrollspy</title>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
  </head>
  <body>
    <div class="row mt-2">
      <div class="col-4">
        <div id="navbarList" class="list-group my-2">
          <a class="list-group-item list-group-item-action" href="#home">Home</a>
          <a class="list-group-item list-group-item-action" href="#services">Services</a>
          <a class="list-group-item list-group-item-action" href="#aboutus">About us</a>
          <a class="list-group-item list-group-item-action" href="#contactus">Contact us</a>
          <a class="list-group-item list-group-item-action" href="#features">Features</a>
        </div>
      </div>
      <div class="col-8">
        <div data-bs-spy="scroll" data-bs-target="#navbarList" data-bs-smooth-scroll="true" class="bg-body-tertiary p-3 rounded-2 my-2" tabindex="0">
          <h4 id="home">Home</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area.</p>
          <h4 id="services">Services</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
          <h4 id="aboutus">About us</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area.</p>
          <h4 id="contactus">Contact us</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
          <h4 id="features">Features</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. </p>
        </div>
        </div>
      </div>
    </div>
  </body>
  </html>

Simple anchors

Scrollspy works on all <a> anchor elements, not restricted to nav elements and list groups.

Example

You can edit and try running this code using Edit & Run option.

  <!DOCTYPE html>
  <html lang="en">
  <head>
    <title>Bootstrap - Scrollspy</title>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
  </head>
  <body>
    <div class="row">
      <div class="col-4">
        <div id="listUsingAnchor" class="text-center">
          <nav class="nav nav-pills flex-column mx-3">
            <a class="nav-link active" href="#home">Home</a>
            <a class="nav-link" href="#services">Services</a>
            <a class="nav-link" href="#aboutus">About us</a>
            <a class="nav-link" href="#contactus">Contact us</a>
            <a class="nav-link" href="#features">Features</a>
        </nav>
        </div>
      </div>
      <div class="col-8">
        <div data-bs-spy="scroll" data-bs-target="#listUsingAnchor" data-bs-offset="0" data-bs-smooth-scroll="true" class="bg-body-tertiary p-3 rounded-2 my-2" tabindex="0">
          <h4 id="home">Home</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group. Scrollspy works with nav and list group.</p>
          <h4 id="services">Services</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
          <h4 id="aboutus">About us</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
          <h4 id="contactus">Contact us</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group. Scrollspy works with nav and list group.</p>
          <h4 id="features">Features</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group. Scrollspy works with nav and list group.</p>
        </div>
      </div>
    </div>
  </body>
  </html>

Non-visible elements

Non-visible elements will be disregarded, and their corresponding nav items will not be assigned the .active class. Scrollspy instances that are initialized within an non-visible wrapper ignores all target elements. Use refresh method in case the wrapper becomes visible. This helps check for observable elements .

Example

  document.querySelectorAll('#nav-tab>[data-bs-toggle="tab"]').forEach(el => {
    el.addEventListener('shown.bs.tab', () => {
      const target = el.getAttribute('data-bs-target')
      const scrollElem = document.querySelector(`${target} [data-bs-spy="scroll"]`)
      bootstrap.ScrollSpy.getOrCreateInstance(scrollElem).refresh()
    })
  })

Usage

Via data attributes

Add data-bs-spy="scroll" to the element to spy on (usually the <body>) to quickly add scroll spy behavior to topbar navigation. Then, specifying the id or class name of the parent element of any Bootstrap .nav component using the "data-bs-target" attribute.

Example

You can edit and try running this code using Edit & Run option.

    <!DOCTYPE html>
    <html lang="en">
    <head>
     <title>Bootstrap - Scrollspy</title>
     <meta charset="UTF-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
     <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
    </head>
     <body data-bs-spy="scroll" data-bs-target="#navbarDataAttribute">
       <div id="navbarDataAttribute" class="my-2">
         <ul class="nav nav-pills" role="pillslist"> 
             <li class="nav-item">
               <a class="nav-link" href="#scrollspyFirstTitle">Home</a>
             </li>
             <li class="nav-item">
               <a class="nav-link" href="#scrollspySecondTitle">Services</a>
             </li>
             <li class="nav-item">
               <a class="nav-link" href="#scrollspyThirdTitle">About us</a>
             </li>
             <li class="nav-item">
               <a class="nav-link" href="#scrollspyFourthTitle">Contact us</a>
             </li>
             <li class="nav-item">
               <a class="nav-link" href="#scrollspyFifthTitle">Features</a>
             </li>
         </ul>
          
         <div data-bs-spy="scroll" data-bs-target="#navbarDataAttribute" data-bs-root-margin="0px 0px -40%" data-bs-smooth-scroll="true" class="bg-body-tertiary p-3 rounded-2 my-2" tabindex="0">
           <h4 id="scrollspyFirstTitle">Home</h4>
           <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group. Scrollspy works with nav and list group.</p>
           <h4 id="scrollspySecondTitle">Services</h4>
           <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
           <h4 id="scrollspyThirdTitle">About us</h4>
           <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
           <h4 id="scrollspyFourthTitle">Contact us</h4>
           <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group. Scrollspy works with nav and list group.</p>
           <h4 id="scrollspyFifthTitle">Features</h4>
           <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
         </div>
       </div>
     </body>
    </html>

Via JavaScript

  • To enable scrollspy behavior on your topbar navigation, add data-bs-spy="scroll" to the desired element (usually the <body> tag).

  • Inside the <script> tag apply scroll spy to a component using the identifier or class like "navbarJavaScript".

Example

You can edit and try running this code using Edit & Run option.

  <!DOCTYPE html>
  <html lang="en">
  <head>
    <title>Bootstrap - Scrollspy</title>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
  </head>
    <body data-bs-spy="scroll" data-bs-target="#navbarJavaScript">
      <div id="navbarJavaScript">
        <ul class="nav nav-pills" role="pillslist"> 
            <li class="nav-item">
              <a class="nav-link" href="#scrollspyFirstTitle">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#scrollspySecondTitle">Services</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#scrollspyThirdTitle">About us</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#scrollspyFourthTitle">Contact us</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#scrollspyFifthTitle">Features</a>
            </li>
        </ul>
        
        <div data-bs-spy="scroll" data-bs-root-margin="0px 0px -40%" data-bs-smooth-scroll="true" class="scrollspy-example bg-body-tertiary p-3 rounded-2" tabindex="0">
          <h4 id="scrollspyFirstTitle">Home</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
          <h4 id="scrollspySecondTitle">Services</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
          <h4 id="scrollspyThirdTitle">About us</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
          <h4 id="scrollspyFourthTitle">Contact us</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group. Scrollspy works with nav and list group.</p>
          <h4 id="scrollspyFifthTitle">Features</h4>
          <p>Bootstrap Scrollspy targets the navigation bar contents automatically on scrolling the area. Scrollspy works with nav and list group.</p>
        </div>
      </div>
  
      <script>
        const scrollSpy = new bootstrap.ScrollSpy(document.body, {
          target: '#navbarJavaScript'
        })
      </script>
    </body>
  </html>

Otpions

Options can be provided through data attributes or JavaScript

  • To add an option name to data-bs-, as in data-bs-animation={value}," use either data attributes or JavaScript. If using data attributes, use "kebab-case" instead of "camelCase" for the option name. For example, use data-bs-custom-class="beautifier" instead of data-bs-custom-class="beautifier".

  • Bootstrap 5.2.0 has added a new feature called data-bs-config attribute to store basic component configurations as a JSON string. If an element has both data-bs-config and separate data attributes, the separate data attributes' values take precedence over those in data-bs-config. Even, existing data attributes can also store JSON values.

  • Data-bs-config, data-bs-, and js objects are combined to create the final configuration object, where the most recent key-value overrides all others.

CSS Properties

The table describes the properties and their corresponding values for a ScrollSpy plugin.

Name Type Default Description

rootMargin

string

0px 0px -25%

Intersection Observer rootMargin valid units, when calculating scroll position.

smoothScroll

boolean

false

Enables smooth scrolling when a user clicks on a link that refers to ScrollSpy observables.

target

string, DOM element

null

Specifies element to apply Scrollspy plugin.

threshold

array

[0.1, 0.5, 1]

IntersectionObserver

threshold valid input, when calculating scroll position.
Advertisements