preline
Version:
Preline UI is an open-source set of prebuilt UI components based on the utility-first Tailwind CSS framework.
306 lines (224 loc) • 11 kB
Markdown
# Scroll Nav
Scroll Nav is a versatile and lightweight JavaScript plugin designed to enhance navigation menus with smooth scrolling capabilities.
[](https://www.npmjs.com/package/@preline/scroll-nav) [](https://opensource.org/licenses/MIT) [](https://preline.co/plugins/scroll-nav.html)
## Contents
- [Overview](#overview)
- [Installation](#installation)
- [Basic usage](#basic-usage)
- [Configuration Options](#configuration-options)
- [JavaScript API](#javascript-api)
- [Common Patterns](#common-patterns)
- [License](#license)
## 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.
```bash
npm i /scroll-nav
```
### CSS
Use [``](https://tailwindcss.com/docs/functions-and-directives#source-directive) to register the plugin's JavaScript path for Tailwind CSS scanning, then [`@import`](https://tailwindcss.com/docs/functions-and-directives#import-directive) the plugin's CSS files into your Tailwind CSS file.
```css
"tailwindcss";
/* @preline/scroll-nav */
"../node_modules/@preline/scroll-nav/*.js";
"./node_modules/@preline/scroll-nav/variants.css";
"./node_modules/@preline/scroll-nav/theme.css";
```
### JavaScript
Include the JavaScript that powers the interactive elements near the end of your `</body>` tag:
```html
<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.
```html
<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.
`/scroll-nav` is the auto-init entry: it scans the DOM and initializes matching elements automatically.
```js
import "@preline/scroll-nav";
```
`/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.
```js
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 `/` 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.
```html
<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 element
- `hs-scroll-nav-prev`: Required class on the previous button
- `hs-scroll-nav-next`: Required class on the next button
- `hs-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 `autoCentering` is 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:**
```html
<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)<br>`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)<br>`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)<br>`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**
```javascript
// 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**
```javascript
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**
```javascript
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**
```javascript
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.
```html
<div data-hs-scroll-nav='{
"autoCentering": true
}'>
<!-- Navigation structure -->
</div>
```
### Pattern 2: Programmatic Navigation
Control navigation programmatically.
```html
<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](https://opensource.org/licenses/MIT).