@preline/scroll-nav
v4.2.0
Published
Preline UI is an open-source set of prebuilt UI components based on the utility-first Tailwind CSS framework.
Readme
Scroll Nav
Scroll Nav is a versatile and lightweight JavaScript plugin designed to enhance navigation menus with smooth scrolling capabilities.
Contents
Overview
The Scroll Nav component provides horizontal scrolling navigation with previous/next buttons and automatic centering. It's ideal for navigation menus with many items that need to be scrolled horizontally.
Key Features:
- Horizontal scrolling navigation
- Previous/next navigation buttons
- Automatic centering of active items
- Programmatic control via JavaScript API
- Smooth scrolling animations
- Current state tracking
Installation
To get started, install Scroll Nav plugin via npm, else you can skip this step if you are already using Preline UI as a package.
npm i @preline/scroll-navCSS
Use @source to register the plugin's JavaScript path for Tailwind CSS scanning, then @import the plugin's CSS files into your Tailwind CSS file.
@import "tailwindcss";
/* @preline/scroll-nav */
@source "../node_modules/@preline/scroll-nav/*.js";
@import "./node_modules/@preline/scroll-nav/variants.css";
@import "./node_modules/@preline/scroll-nav/theme.css";JavaScript
Include the JavaScript that powers the interactive elements near the end of your </body> tag:
<script src="./node_modules/@preline/scroll-nav/index.js"></script>Manual Initialization
Use the non-auto entry if you need manual initialization. In this mode, automatic initialization on page load is not included, so the component should be initialized explicitly.
<script type="module">
import HSScrollNav from "@preline/scroll-nav/non-auto.mjs";
new HSScrollNav(document.querySelector("#scroll-nav"));
</script>Via Bundler
When using a bundler (Vite, webpack, etc.), import the plugin directly as an ES module.
@preline/scroll-nav is the auto-init entry: it scans the DOM and initializes matching elements automatically.
import "@preline/scroll-nav";@preline/scroll-nav/non-auto is the manual entry: use it when you want explicit control over when initialization happens, either via autoInit() or by creating a specific instance yourself.
import HSScrollNav from "@preline/scroll-nav/non-auto";
HSScrollNav.autoInit();
// Or initialize a specific element manually
const el = document.querySelector("#scroll-nav");
if (el) new HSScrollNav(el);TypeScript
This package ships with TypeScript type definitions. No additional @types/ package is needed.
Basic usage
The following example demonstrates the minimal HTML structure required for a scroll nav component. This is a base template without custom styling - you can apply your own CSS classes and styles as needed. The navigation items scroll horizontally with previous/next buttons.
<div data-hs-scroll-nav class="relative px-6">
<button type="button" class="hs-scroll-nav-prev">Previous</button>
<nav class="hs-scroll-nav-body flex flex-nowrap overflow-x-auto snap-x snap-mandatory">
<a class="snap-start" href="#">Electronics</a>
<a class="snap-start" href="#">Clothing</a>
<a class="snap-start" href="#">House & Garden</a>
<a class="snap-start" href="#">Baby Care</a>
<a class="snap-start" href="#">Home appliances</a>
<a class="snap-start" href="#">Sports & Fitness</a>
<a class="snap-start" href="#">Constraction & Renovation</a>
<a class="snap-start" href="#">Food</a>
<a class="snap-start" href="#">Pharmacy</a>
<a class="snap-start" href="#">Pet Products</a>
<a class="snap-start" href="#">Books</a>
<a class="snap-start" href="#">Tourism, fishing, hunting</a>
<a class="snap-start" href="#">Furniture</a>
<a class="snap-start" href="#">Jewelery</a>
<a class="snap-start" href="#">Accessories</a>
<a class="snap-start" href="#">Games & Consoles</a>
<a class="snap-start" href="#">Stationery</a>
<a class="snap-start" href="#">Digital Goods</a>
<a class="snap-start" href="#">Music</a>
</nav>
<button type="button" class="hs-scroll-nav-next">Next</button>
</div>Structure Requirements:
data-hs-scroll-nav: Required on the container elemenths-scroll-nav-prev: Required class on the previous buttonhs-scroll-nav-next: Required class on the next buttonhs-scroll-nav-body: Required class on the scrollable navigation container- Navigation items inside the scrollable container
Initial State:
- Navigation items are visible
- Previous/next buttons are enabled/disabled based on scroll position
- Active item can be centered automatically if
autoCenteringis enabled
Configuration Options
Data Options
Data options are specified in the data-hs-scroll-nav attribute.
| Attribute | Target Element | Type | Default | Description |
| --- | --- | --- | --- | --- |
| data-hs-scroll-nav | Container | - | - | Activate a Scroll Nav by specifying on an element. Should be added to the container. |
| :autoCentering | Inside data-hs-scroll-nav | boolean | false | Defines whether the Scroll Nav should align with the active item when the window loads. When true, the active item is automatically centered on page load. |
Example:
<div data-hs-scroll-nav='{
"autoCentering": true
}'>
<!-- Navigation structure -->
</div>Required CSS Classes
These classes define the structure and must be present for the scroll nav to function.
| Class | Required On | Purpose |
| --- | --- | --- |
| hs-scroll-nav-prev | Previous button | Identifies the previous navigation button |
| hs-scroll-nav-next | Next button | Identifies the next navigation button |
| hs-scroll-nav-body | Scrollable container | Identifies the scrollable navigation container |
Tailwind Modifiers
| Name | Description |
| --- | --- |
| hs-scroll-nav-active:* | The class is applied to the navigation item to style the currently active element. |
| hs-scroll-nav-disabled:* | The class is added to the prev/next buttons for style the disabled state. |
JavaScript API
The HSScrollNav object is available in the global window object after the plugin is loaded.
Instance Methods
These methods are called on a scroll nav instance.
| Method | Parameters | Return Type | Description |
| --- | --- | --- | --- |
| getCurrentState() | None | IScrollNavCurrentState | Retrieves the currently visible first, last, and center elements within the scrollable navigation container. Returns an object with first, last, and center properties. |
| goTo(el, cb) | el: Element (target element)cb: Function (optional callback) | void | Smoothly scrolls the navigation container to bring the specified element into view. The callback function is executed after scrolling completes. |
| centerElement(el, behavior) | el: HTMLElement (target element)behavior: ScrollBehavior (optional, "auto" | "smooth") | void | Scrolls the navigation container to position the specified element at the center of the visible area. Default behavior is "smooth". |
| destroy() | None | void | Destroys the scroll nav instance, removes all generated markup, classes, and event listeners. Use when removing scroll nav from DOM. |
Static Methods
These methods are called directly on the HSScrollNav class.
| Method | Parameters | Return Type | Description |
| --- | --- | --- | --- |
| HSScrollNav.getInstance(target, isInstance) | target: HTMLElement \| string (CSS selector)isInstance: boolean (optional) | HTMLElement \| { id: string \| number, element: HSScrollNav } \| null | Returns the scroll nav instance or element associated with the target. If isInstance is true, returns collection item object { id, element } where element is the HSScrollNav instance. If isInstance is false or omitted, returns the DOM element (HTMLElement). Returns null if scroll nav instance is not found. |
Usage Examples
Example 1: Getting current state
// Get the scroll nav instance
const instance = HSScrollNav.getInstance('#hs-scroll-nav', true);
if (instance) {
const { element } = instance;
// Get current state
const state = element.getCurrentState();
console.log('First visible:', state.first);
console.log('Last visible:', state.last);
console.log('Center visible:', state.center);
}Example 2: Scrolling to an element
const instance = HSScrollNav.getInstance('#hs-scroll-nav', true);
if (instance) {
const { element } = instance;
const targetLink = document.querySelector('#hs-e-commerce-link');
// Scroll to element
element.goTo(targetLink, () => {
console.log('Scrolled to element!');
// Perform actions after scrolling
});
}Example 3: Centering an element
const instance = HSScrollNav.getInstance('#hs-scroll-nav', true);
if (instance) {
const { element } = instance;
const targetLink = document.querySelector('#hs-e-commerce-link');
// Center element
element.centerElement(targetLink, 'smooth');
}Example 4: Destroying scroll nav instance
const instance = HSScrollNav.getInstance('#hs-scroll-nav', true);
if (instance) {
const { element } = instance;
const removeBtn = document.querySelector('#hs-remove-btn');
removeBtn.addEventListener('click', () => {
// Clean up before removing from DOM
element.destroy();
// Now safe to remove the element
document.querySelector('#hs-scroll-nav').remove();
});
}Common Patterns
Pattern 1: Auto-centering Active Item
Automatically center the active item on page load.
<div data-hs-scroll-nav='{
"autoCentering": true
}'>
<!-- Navigation structure -->
</div>Pattern 2: Programmatic Navigation
Control navigation programmatically.
<div id="hs-scroll-nav-first" data-hs-scroll-nav>
<!-- Navigation structure -->
</div>
<script>
const instance = HSScrollNav.getInstance('#hs-scroll-nav-first', true);
if (instance) {
const { element } = instance;
// Scroll to specific item
const item = document.querySelector('#hs-item-electronics');
element.goTo(item);
}
</script>License
Copyright (c) 2026 Preline Labs.
Licensed under the MIT License.
