Scrollspy
Spying on elements in a scrollable container, automatically highlights their related targets based on scroll position to indicate which element is currently active in the viewport.
How it works
Scrollspy spys on elements in a scrollable container and calculate the position of the “spied” elements to determine if a certain element is scrolled into view. If it is, the configured classname will be added to it’s related target element. To make scrollspy work properly, you have to instantiate a Scrollspy instance with three parameters.
- An array of target elements you want to highlight when the “spied” element is scrolled into view. The
idof “spied” element must be referenced by target element viahrefattribute. If the natural structure of target elements is a tree, you must construct a nested array to represent the tree before passing it toScrollspyinstance. - “Spied” container, either
document.bodyor user specified element. - A config object, see config section bellow for more details.
Examples
Spy on document.body
Check the live demo.
In this example, headings of the article are “spied” elements, and anchors in the table of content are target elements, and the scrollable container is document.body. What we want is whenever a heading is scrolled into view, highlighting it’s related item in the table of content. The JavaScript code is like bellow:
(function () {
function appendChildren(root, children) {
return [].filter
.call(root.children, (el) => el.nodeName === "LI")
.forEach((liElem) => {
const aElem = liElem.querySelector(":scope > a");
// push the anchor element to target elements array
children.push(aElem);
const ulElem = liElem.querySelector(":scope > ul");
// find anchors and push to target elements array recursively
if (ulElem) {
const nextElements = [];
children.push(nextElements);
appendChildren(ulElem, nextElements);
}
});
}
// target elements array
const tree = [];
appendChildren(document.getElementById("menu"), tree);
// tree is a nested array represents the tree structure of all anchors like this:
// [item1, [item1.1, item1.2, [item1.2.1, item1.2.2]], item2, item3...]
// the plain item in the target elements array represents a tree node, and the array item represents subtree of it's previous item.
new kutsu.Scrollspy(tree, document.body, {
activeClassName: "text-red-500",
});
})();
Spy on scrollable container
Scrollspy can also spys on user specified scrollable container instead of document.body.
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 2-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-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.
Config
| Name | Type | Default | Description |
|---|---|---|---|
| activeClassName | undefined | string | undefined | Classes added to target element when its referenced element scrolls into view. |
| offset | undefined | number | (() => number) | 0 | Offset from the top of the viewport when calculating active element. Use a function for dynamic values (e.g., fixed navbar height). |
Methods
| Method | Description |
|---|---|
| refresh | Refresh the state. If the structure of target elements changed, this method must be called with the updated target elements array. |