ktuiktui
ktuiktui
ComponentsDocsProducts

Getting Started

IntroductionInstallationJavaScriptDark modeRTLReferencesChangelog

Components

AccordionAvatarAlertBadgeBreadcrumbButtonCardCheckboxCollapseDatatableDatepickerDismissDrawerDropdownImage InputInputKbdLinkModalPaginationProgressRadio GroupReparentScrollableScrollspyScrolltoSelectSeparatorSkeletonStepperStickySwitchTabsTextareaTheme SwitchToggleToggle GroupToggle PasswordTooltip
©2025 KTUI. All rights reserved.
A project by Keenthemes
Privacy Policy
Docs
Scrollspy

Scrollspy

Tailwind Scrollspy component enhances user navigation by highlighting active links as users scroll through different sections of a webpage. This feature is particularly useful for single-page applications and long-form content, providing a clear visual indicator of the user's current position on the page.

Examples

Basic Usage

Implement a Tailwind Scrollspy within a scrollable container to automatically highlight navigation links as you scroll through various sections.

<div class="flex gap-8 w-full rounded-md p-6 border border-border">
  <div
    data-kt-scrollspy="true"
    data-kt-scrollspy-target="#scrollable"
    data-kt-scrollspy-offset="100px"
    class="flex flex-col relative gap-2 shrink-0 w-[125px]"
  >
    <a
      href="#section_1"
      data-kt-scrollspy-anchor="true"
      class="kt-btn kt-btn-outline"
      >Section 1</a
    ><a
      href="#section_2"
      data-kt-scrollspy-anchor="true"
      class="kt-btn kt-btn-outline"
      >Section 2</a
    ><a
      href="#section_3"
      data-kt-scrollspy-anchor="true"
      class="kt-btn kt-btn-outline"
      >Section 3</a
    ><a
      href="#section_4"
      data-kt-scrollspy-anchor="true"
      class="kt-btn kt-btn-outline"
      >Section 4</a
    >
  </div>
  <div
    class="kt-scrollable overflow-y-auto flex flex-col grow gap-5 h-[300px] pe-2"
    id="scrollable"
  >
    <div id="section_1">
      <h3 class="mb-2 text-base text-mono font-semibold">Section 1</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
    <div id="section_2">
      <h3 class="mb-2 text-base text-mono font-semibold">Section 2</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
    <div id="section_3">
      <h3 class="mb-2 text-base text-mono font-semibold">Section 3</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
    <div id="section_4">
      <h3 class="mb-2 text-base text-mono font-semibold">Section 4</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
  </div>
</div>

Nested

Implement a Tailwind Scrollspy within a scrollable container to automatically highlight nested navigation links as you scroll through various sections.

<div class="flex gap-8 w-full rounded-xl p-6 border border-border">
  <div
    data-kt-scrollspy="true"
    data-kt-scrollspy-target="#scrollable"
    data-kt-scrollspy-offset="150px"
    class="flex flex-col relative before:absolute before:start-[11px] before:top-0 before:bottom-0 before:border-s before:border-border gap-1 shrink-0 w-[125px]"
  >
    <div class="flex flex-col" data-kt-scrollspy-group="true">
      <a
        href="#section_2_1"
        data-kt-scrollspy-anchor="true"
        class="flex items-center rounded-lg ps-2.5 pe-2.5 py-2.5 gap-1.5 text-sm font-medium text-foreground hover:text-primary kt-scrollspy-active:text-primary"
        ><span
          class="flex w-1.5 relative before:absolute before:top-0 before:start-px before:size-1.5 before:rounded-full before:-translate-x-2/4 before:-translate-y-2/4"
        ></span
        >Section 1</a
      >
      <div class="flex flex-col">
        <a
          href="#section_2_1_1"
          data-kt-scrollspy-anchor="true"
          class="flex items-center rounded-lg ps-2.5 pr-2.5 py-2.5 gap-3.5 border border-transparent text-sm font-medium text-foreground kt-scrollspy-active:text-primary"
          ><span
            class="flex w-1.5 relative before:absolute before:top-0 before:start-px before:size-1.5 before:rounded-full before:-translate-x-2/4 before:-translate-y-2/4 kt-scrollspy-active:before:bg-primary"
          ></span
          >Sub item 1</a
        ><a
          href="#section_2_1_2"
          data-kt-scrollspy-anchor="true"
          class="flex items-center rounded-lg ps-2.5 pr-2.5 py-2.5 gap-3.5 border border-transparent text-sm font-medium text-foreground kt-scrollspy-active:text-primary"
          ><span
            class="flex w-1.5 relative before:absolute before:top-0 before:start-px before:size-1.5 before:rounded-full before:-translate-x-2/4 before:-translate-y-2/4 kt-scrollspy-active:before:bg-primary"
          ></span
          >Sub item 2</a
        ><a
          href="#section_2_1_3"
          data-kt-scrollspy-anchor="true"
          class="flex items-center rounded-lg ps-2.5 pr-2.5 py-2.5 gap-3.5 border border-transparent text-sm font-medium text-foreground kt-scrollspy-active:text-primary"
          ><span
            class="flex w-1.5 relative before:absolute before:top-0 before:start-px before:size-1.5 before:rounded-full before:-translate-x-2/4 before:-translate-y-2/4 kt-scrollspy-active:before:bg-primary"
          ></span
          >Sub item 3</a
        >
      </div>
    </div>
    <a
      href="#section_2_2"
      data-kt-scrollspy-anchor="true"
      class="flex items-center rounded-lg ps-2.5 pr-2.5 py-2.5 gap-1.5 border border-transparent text-sm font-medium text-foreground kt-scrollspy-active:text-primary"
      ><span
        class="flex w-1.5 relative before:absolute before:top-0 before:start-px before:size-1.5 before:rounded-full before:-translate-x-2/4 before:-translate-y-2/4 kt-scrollspy-active:before:bg-primary"
      ></span
      >Section 2</a
    >
    <div class="flex flex-col" data-kt-scrollspy-group="true">
      <a
        href="#section_2_3"
        data-kt-scrollspy-anchor="true"
        class="flex items-center rounded-lg ps-2.5 pe-2.5 py-2.5 gap-1.5 text-sm font-medium text-foreground hover:text-primary kt-scrollspy-active:text-primary"
        ><span
          class="flex w-1.5 relative before:absolute before:top-0 before:start-px before:size-1.5 before:rounded-full before:-translate-x-2/4 before:-translate-y-2/4"
        ></span
        >Section 3</a
      >
      <div class="flex flex-col">
        <a
          href="#section_2_3_1"
          data-kt-scrollspy-anchor="true"
          class="flex items-center rounded-lg ps-2.5 pr-2.5 py-2.5 gap-3.5 border border-transparent text-sm font-medium text-foreground kt-scrollspy-active:text-primary"
          ><span
            class="flex w-1.5 relative before:absolute before:top-0 before:start-px before:size-1.5 before:rounded-full before:-translate-x-2/4 before:-translate-y-2/4 kt-scrollspy-active:before:bg-primary"
          ></span
          >Sub item 4</a
        ><a
          href="#section_2_3_2"
          data-kt-scrollspy-anchor="true"
          class="flex items-center rounded-lg ps-2.5 pr-2.5 py-2.5 gap-3.5 border border-transparent text-sm font-medium text-foreground kt-scrollspy-active:text-primary"
          ><span
            class="flex w-1.5 relative before:absolute before:top-0 before:start-px before:size-1.5 before:rounded-full before:-translate-x-2/4 before:-translate-y-2/4 kt-scrollspy-active:before:bg-primary"
          ></span
          >Sub item 5</a
        ><a
          href="#section_2_3_3"
          data-kt-scrollspy-anchor="true"
          class="flex items-center rounded-lg ps-2.5 pr-2.5 py-2.5 gap-3.5 border border-transparent text-sm font-medium text-foreground kt-scrollspy-active:text-primary"
          ><span
            class="flex w-1.5 relative before:absolute before:top-0 before:start-px before:size-1.5 before:rounded-full before:-translate-x-2/4 before:-translate-y-2/4 kt-scrollspy-active:before:bg-primary"
          ></span
          >Sub item 6</a
        >
      </div>
    </div>
    <a
      href="#section_2_4"
      data-kt-scrollspy-anchor="true"
      class="flex items-center rounded-lg ps-2.5 pr-2.5 py-2.5 gap-1.5 border border-transparent text-sm font-medium text-foreground kt-scrollspy-active:text-primary"
      ><span
        class="flex w-1.5 relative before:absolute before:top-0 before:start-px before:size-1.5 before:rounded-full before:-translate-x-2/4 before:-translate-y-2/4 kt-scrollspy-active:before:bg-primary"
      ></span
      >Section 4</a
    >
  </div>
  <div
    class="kt-scrollable overflow-y-auto flex flex-col gap-5 h-[400px] grow pe-2"
    id="scrollable"
  >
    <div id="section_2_1_1">
      <h3 class="mb-2 text-base text-mono font-semibold">Sub item 1</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
    <div id="section_2_1_2">
      <h3 class="mb-2 text-base text-mono font-semibold">Sub item 2</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
    <div id="section_2_1_3">
      <h3 class="mb-2 text-base text-mono font-semibold">Sub item 3</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
    <div id="section_2_2">
      <h3 class="mb-2 text-base text-mono font-semibold">Section 2</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
    <div id="section_2_3_1">
      <h3 class="mb-2 text-base text-mono font-semibold">Sub item 4</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
    <div id="section_2_3_2">
      <h3 class="mb-2 text-base text-mono font-semibold">Sub item 5</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
    <div id="section_2_3_3">
      <h3 class="mb-2 text-base text-mono font-semibold">Sub item 6</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
    <div id="section_2_4">
      <h3 class="mb-2 text-base text-mono font-semibold">Section 4</h3>
      <div class="rounded-lg bg-muted w-full grow h-[500px]"></div>
    </div>
  </div>
</div>

Component API

Options

These data attributes allow you to set options for the scrollspy component during auto initialization.

OptionTypeDefaultDescription
data-kt-scrollspy-targetstring"body"Specifies the ID selector of the scrollable element that the scrollspy should monitor.
data-kt-scrollspy-offsetnumber0Defines the number of pixels to offset when activating each section of the scrollspy, allowing for fine-tuned control over the activation point.
data-kt-scrollspy-smoothbooleantrueEnables smooth scrolling animation when navigating between sections in the scrollspy, providing a more fluid user experience.

Selectors

This table details the custom classes and data attributes used by the scrollspy component.

NameDescription
Data Attributes
data-kt-scrollspy="true"A selector used to auto-initialize the scrollspy object on page load.
data-kt-scrollspy-anchor="true"Indicates a scrollspy navigation item element where the href attribute value provides the linked content ID selector, facilitating scroll tracking and navigation highlighting.
data-kt-scrollspy-group="true"Specifies a group element that contains nested child anchors, organizing them into a hierarchy for the scrollspy navigation.
Classes
activeSets a specific scrollspy item to be open initially when used togather with data-kt-scrollspy-item selector.

Tailwind Modifiers

Custom modifiers to control the scrollspy’s style and behavior with Tailwind classes.

NameDescription
kt-scrollspy-active:*A custom Tailwind variant the scrollspy item becomes active.

Methods

Use KTScrollspy component's API methods to programmatically control its behavior.

MethodDescription
new KTScrollspy(element, options)Creates an object instance of KTScrollspy class for the given DOM element and configuration options .
scrollTo(anchorElement)Programmatically scrolls to the specified anchor element, aligning it within the viewport according to the scrollspy's configuration. This method facilitates direct navigation to scrollspy sections without user-initiated scrolling.
update()Refreshes and recalculates the positions and states of all scrollspy elements, ensuring that the scrollspy functionality accurately reflects the current layout and scroll position of the page.
updateAnchor(anchorElement)Updates the specific anchor element within the scrollspy system, recalculating its position and state based on the current scroll position. This is useful for dynamically added content or changes in the layout that affect only certain anchors.
isActive(anchorElement)Returns a boolean value indicating whether the specified anchor element is currently active within the scrollspy system, allowing for custom logic or styles to be applied based on the active state of the element.
getOption(name)Retrieves the value of a configuration option by name parameter from a KTScrollspy instance.
getElement()Retrieves the DOM element linked to a specific KTScrollspy instance.
on(eventName, handler)Allows attaching event listeners to the KTScrollspy custom events using the eventName and eventId string parameters. These events enable programmatic interaction based on user actions or internal state changes of KTScrollspy. The function returns string as a unique identifier for the registered listener, allowing you to remove it later if needed.
off(eventName, eventId)Removes an event listener for the eventName and eventId parameters attached with the on method.
dispose()Removes the KTScrollspy instance from an element, including any associated data stored on the DOM element.
const scrollspyItemEl = document.querySelector('#my_scrollspy_item');
const scrollspyEl = document.querySelector('#my_scrollspy');
const scrollspy = KTScrollspy.getInstance(scrollspyEl);
 
scrollspy.scrollTo(scrollspyItemEl);
scrollspy.update();

To initialize Tailwind Scrollspy with JavaScript, use data-scrollspy="false" attribute instead. This prevents automatic initialization on page load.

Utilities

Manage and interact with KTScrollspy instances using these static methods of KTScrollspy JavaScript class.

MethodDescription
init()Automatically initializes KTScrollspy object for all elements with the data-kt-scrollspy="true" attribute on page load.
createInstances()Allows to create KTScrollspy instances for all elements that have been dynamically added to the DOM but haven't been activated yet.
getInstance(element)Returns the KTScrollspy object associated with the given DOM element element .
getOrCreateInstance(element)Returns the existing KTScrollspy object for the provided DOM element element , or creates a new instance if none exists, then returns the same.
// Initialize all scrollspys
KTScrollspy.init()
 
// Initialzie pending scrollspys
KTScrollspy.createInstances();
 
// Get scrollspy object
const scrollspyEl = document.querySelector('#my_scrollspy');
const scrollspy = KTScrollspy.getInstance(scrollspyEl);

Events

KTScrollspy custom events allows you to register callback functions(event listeners) that will be invoked automatically whenever specific custom events are triggered within the component.

EventDescription
activateThis event fires on the scroll element whenever an anchor is activated by the scrollspy.
const scrollspyEl = document.querySelector('#my_scrollspy');
const scrollspy = KTScrollspy.getInstance(scrollspyEl);
 
scrollspy.on('activate', (element) => {
	console.log('anchor activate event');
});
PreviouseScrollableNextScrollto

On This Page

  • Examples
    • Basic Usage
    • Nested
  • Component API
    • Options
    • Selectors
    • Tailwind Modifiers
    • Methods
    • Utilities
    • Events