Powered by NeGD | MeitY Government of India® UX4G
Scrollspy
To show which link is active in the viewport, automatically update UX4G navigation or list group components based on scroll position.
How it works #
When the element with the id referred to by the anchor's href is scrolled into view, Scrollspy toggles the .active class on anchor () elements. Although it can be used with any anchor element on the current page, Scrollspy functions best when combined with a UX4G navigation component or list group. This is how it goes.
To get started, scrollspy needs two components: a scrollable container and a navigation, list group, or basic series of links. The <body> element or a custom element with a set height and overflow-y: scroll can be the scrollable container.
Add the data-bs-spy="scroll" and data-bs-target="#navId" attributes to the scrollable container, where navId is the distinctive id of the associated navigation. To ensure keyboard accessibility, be sure to additionally include a tabindex="0".
The associated navigation's anchor links have an.active class that is added and removed as you scroll the "spied" container. Links that don't have resolvable id targets are ignored. A home, for instance, must match to something like a <div id="home">home</div> in the DOM.
Invisible target items will not be taken into account. See the section below on Non-Visible Elements.
Examples #
Navbar #
Watch the active class change as the space is scrolled below the navbar. Watch as the dropdown items are highlighted when you open the dropdown menu.
<nav id="navbar-example2" class="navbar bg-light px-3 mb-3">
<a class="navbar-brand" href="#">Navbar</a>
<ul class="nav nav-pills">
<li class="nav-item">
<a class="nav-link" href="#scrollspyHeading1">First</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#scrollspyHeading2">Second</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">Dropdown</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#scrollspyHeading3">Third</a></li>
<li><a class="dropdown-item" href="#scrollspyHeading4">Fourth</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#scrollspyHeading5">Fifth</a></li>
</ul>
</li>
</ul>
</nav>
<div data-bs-spy="scroll" data-bs-target="#navbar-example2" data-bs-root-margin="0px 0px -40%" data-bs-smooth-scroll="true" class="scrollspy-example bg-light p-3 rounded-2" tabindex="0">
<h4 id="scrollspyHeading1">First heading</h4>
<p>...</p>
<h4 id="scrollspyHeading2">Second heading</h4>
<p>...</p>
<h4 id="scrollspyHeading3">Third heading</h4>
<p>...</p>
<h4 id="scrollspyHeading4">Fourth heading</h4>
<p>...</p>
<h4 id="scrollspyHeading5">Fifth heading</h4>
<p>...</p>
</div>
RESULT
First heading
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Second heading
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Third heading
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Fourth heading
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Fifth heading
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Nested nav #
As navigate the area below the navbar, see how the active class changes. When accessing the dropdown menu, keep an eye out for the highlighted dropdown options.
<div class="row">
<div class="col-4">
<nav id="navbar-example3" class="h-100 flex-column align-items-stretch pe-4 border-end">
<nav class="nav nav-pills flex-column">
<a class="nav-link" href="#item-1">Item 1</a>
<nav class="nav nav-pills flex-column">
<a class="nav-link ms-3 my-1" href="#item-1-1">Item 1-1</a>
<a class="nav-link ms-3 my-1" href="#item-1-2">Item 1-2</a>
</nav>
<a class="nav-link" href="#item-2">Item 2</a>
<a class="nav-link" href="#item-3">Item 3</a>
<nav class="nav nav-pills flex-column">
<a class="nav-link ms-3 my-1" href="#item-3-1">Item 3-1</a>
<a class="nav-link ms-3 my-1" href="#item-3-2">Item 3-2</a>
</nav>
</nav>
</nav>
</div>
<div class="col-8">
<div data-bs-spy="scroll" data-bs-target="#navbar-example3" data-bs-smooth-scroll="true" class="scrollspy-example-2" tabindex="0">
<div id="item-1">
<h4>Item 1</h4>
<p>...</p>
</div>
<div id="item-1-1">
<h5>Item 1-1</h5>
<p>...</p>
</div>
<div id="item-1-2">
<h5>Item 1-2</h5>
<p>...</p>
</div>
<div id="item-2">
<h4>Item 2</h4>
<p>...</p>
</div>
<div id="item-3">
<h4>Item 3</h4>
<p>...</p>
</div>
<div id="item-3-1">
<h5>Item 3-1</h5>
<p>...</p>
</div>
<div id="item-3-2">
<h5>Item 3-2</h5>
<p>...</p>
</div>
</div>
</div>
</div>
RESULT
Item 1
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Keep in mind that the JavaScript plugin tries to pick the right element among all that may be visible. Multiple visible scrollspy targets at the same time may cause some issues.
Item 1-1
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Keep in mind that the JavaScript plugin tries to pick the right element among all that may be visible. Multiple visible scrollspy targets at the same time may cause some issues.
Item 1-2
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Keep in mind that the JavaScript plugin tries to pick the right element among all that may be visible. Multiple visible scrollspy targets at the same time may cause some issues.
Item 2
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Keep in mind that the JavaScript plugin tries to pick the right element among all that may be visible. Multiple visible scrollspy targets at the same time may cause some issues.
Item 3
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Keep in mind that the JavaScript plugin tries to pick the right element among all that may be visible. Multiple visible scrollspy targets at the same time may cause some issues.
Item 3-1
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Keep in mind that the JavaScript plugin tries to pick the right element among all that may be visible. Multiple visible scrollspy targets at the same time may cause some issues.
Item 3-2
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Keep in mind that the JavaScript plugin tries to pick the right element among all that may be visible. Multiple visible scrollspy targets at the same time may cause some issues.
List group #
Scrollspy also works with .list-groups
. Scroll the area next to the list group and watch the active class change.
<div class="row"><div class="col-4"><div id="list-example" class="list-group"><a class="list-group-item list-group-item-action" href="#list-item-1">Item 1</a><a class="list-group-item list-group-item-action" href="#list-item-2">Item 2</a><a class="list-group-item list-group-item-action" href="#list-item-3">Item 3</a><a class="list-group-item list-group-item-action" href="#list-item-4">Item 4</a></div></div><div class="col-8"><div data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" class="scrollspy-example" tabindex="0"><h4 id="list-item-1">Item 1</h4><p>...</p><h4 id="list-item-2">Item 2</h4><p>...</p><h4 id="list-item-3">Item 3</h4><p>...</p><h4 id="list-item-4">Item 4</h4><p>...</p></div></div></div>
RESULT
Item 1
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Item 2
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Item 3
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Item 4
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Simple anchors #
Since Scrollspy may be used on any anchor element in the current document, it is not restricted to nav components and list groups. Watch the .active
class change as scroll the area.
<div class="row">
<div class="col-4">
<div id="simple-list-example" class="d-flex flex-column gap-2 simple-list-example-scrollspy text-center">
<a class="p-1 rounded" href="#simple-list-item-1">Item 1</a>
<a class="p-1 rounded" href="#simple-list-item-2">Item 2</a>
<a class="p-1 rounded" href="#simple-list-item-3">Item 3</a>
<a class="p-1 rounded" href="#simple-list-item-4">Item 4</a>
<a class="p-1 rounded" href="#simple-list-item-5">Item 5</a>
</div>
</div>
<div class="col-8">
<div data-bs-spy="scroll" data-bs-target="#simple-list-example" data-bs-offset="0" data-bs-smooth-scroll="true" class="scrollspy-example" tabindex="0">
<h4 id="simple-list-item-1">Item 1</h4>
<p>...</p>
<h4 id="simple-list-item-2">Item 2</h4>
<p>...</p>
<h4 id="simple-list-item-3">Item 3</h4>
<p>...</p>
<h4 id="simple-list-item-4">Item 4</h4>
<p>...</p>
<h4 id="simple-list-item-5">Item 5</h4>
<p>...</p>
</div>
</div>
</div>
RESULT
Item 1
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Item 2
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Item 3
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Item 4
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Item 5
This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.
Non-visible elements #
Target components that are not visible will be disregarded, and the nav items that they correspond to won't have an .active
class. When launched from a non-visible wrapper, Scrollspy instances will disregard all target items. Once the wrapper is visible, use the refresh function to look for observable items.
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"]`)
ux4g.ScrollSpy.getOrCreateInstance(scrollElem).refresh()
})
})
Usage #
Via data attributes #
Simply add data-bs-spy="scroll"
to the element you wish to spy on (usually the <body>
) to quickly add scrollspy functionality to your top bar navigation. The parent element's id or class name should then be added to the data-bs-target attribute of any UX4G .nav component.
<body data-bs-spy="scroll" data-bs-target="#navbar-example">
...
<div id="navbar-example">
<ul class="nav nav-tabs" role="tablist">
...
</ul>
</div>
...
</body>
Via JavaScript #
const scrollSpy = new ux4g.ScrollSpy(document.body, {
target: '#navbar-example'
})
Options #
Data-bs-animation
can have an option name appended to it, for example, data-bs-animation="value,"
since options can be provided through data attributes or JavaScript. When sending the choices via data attributes, be sure to modify the case type of the option name from "camelCase"
to "kebab-case."
Use data-bs-custom-class="beautifier"
as opposed to data-bs-customClass="beautifier,"
for instance.
Since UX4G v1.0.1, all components have support for the experimental reserved data attribute data-bs-config
, which can store a JSON string for basic component setting. When an element has the data-bs-config='{"delay":0, "title":123}'
and data-bs-title="456"
attributes, the final title value will be 456 and the individual data attributes will take precedence over the values specified on the data-bs-config
. Additionally, JSON variables like data-bs-delay='{"show":0,"hide":150}'
can be stored in existing data attributes.
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. |
Deprecated Options
Up until v5.1.3 we were using offset
& method
options, which are now deprecated and replaced by rootMargin
. To keep backwards compatibility, we will continue to parse a given offset
to rootMargin
, but this feature will be removed in v6.
Methods #
Method | Description |
---|---|
dispose |
Destroys an element’s scrollspy. (Removes stored data on the DOM element) |
getInstance |
Static method to get the scrollspy instance associated with a DOM element. |
getOrCreateInstance |
Static method to get the scrollspy instance associated with a DOM element, or to create a new one in case it wasn’t initialized. |
refresh |
When adding or removing elements in the DOM, you’ll need to call the refresh method. |
Here’s an example using the refresh method:
const dataSpyList = document.querySelectorAll('[data-bs-spy="scroll"]')
dataSpyList.forEach(dataSpyEl => {
UX4G.ScrollSpy.getInstance(dataSpyEl).refresh()
})
Events #
Event | Description |
---|---|
activate.bs.scrollspy |
This event fires on the scroll element whenever an anchor is activated by the scrollspy. |
const firstScrollSpyEl = document.querySelector('[data-bs-spy="scroll"]')
firstScrollSpyEl.addEventListener('activate.bs.scrollspy', () => {
// do something...
})