npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rvanbaalen/custom-scroll

v2.0.0

Published

A lightweight, customizable scrollbar library for JavaScript applications.

Downloads

4

Readme

← See my other Open Source projects

@rvanbaalen/custom-scroll

NPM Downloads GitHub License NPM Version

Description

A lightweight, customizable scrollbar library for JavaScript applications, now with reactive programming support via the @rvanbaalen/signals package. This package provides horizontal and vertical scrollbar components that you can style and control programmatically, perfect for custom UI implementations where native scrollbars don't meet your design requirements.

Features

  • 🔄 Custom horizontal and vertical scrollbars
  • 🎨 Fully stylable through CSS
  • 🖱️ Handles drag operations and track clicks
  • 📏 Automatically sizes thumbs based on content
  • 🔗 Reactive state management using signals
  • 🚀 Programmatic scrolling control
  • 📡 Event-based architecture via signals
  • 💨 Smooth animations and interactions

Installation

Install the package via npm:

npm install @rvanbaalen/custom-scroll

The @rvanbaalen/signals package will be automatically installed as a dependency.

Including the required files

ES Modules (Recommended)

// Import the scrollbar components
import { HorizontalScrollbar, VerticalScrollbar } from '@rvanbaalen/custom-scroll';

// Import the default styles (optional)
import '@rvanbaalen/custom-scroll/scrollbar.css';

Script Tags (Browser)

<!-- Include the signals library first -->
<script src="path/to/node_modules/@rvanbaalen/signals/dist/signals.min.js"></script>
<!-- Then include the scrollbar library -->
<script src="path/to/node_modules/@rvanbaalen/custom-scroll/dist/custom-scroll.min.js"></script>
<!-- Include the styles -->
<link rel="stylesheet" href="path/to/node_modules/@rvanbaalen/custom-scroll/scrollbar.css">

<script>
  // Access via the global namespace
  const { HorizontalScrollbar, VerticalScrollbar } = customScroll;
</script>

Usage

Basic Example

import { HorizontalScrollbar, VerticalScrollbar } from '@rvanbaalen/custom-scroll';

// Create a horizontal scrollbar
const horizontalScrollbar = new HorizontalScrollbar({
  container: document.getElementById('my-container'),
  contentWidth: 2000,  // Total scrollable width in pixels
  visibleWidth: 500,   // Width of the visible area
  onScroll: (scrollX) => {
    // Handle horizontal scroll
    document.getElementById('content').style.transform = `translateX(-${scrollX}px)`;
  }
});

// Create a vertical scrollbar
const verticalScrollbar = new VerticalScrollbar({
  container: document.getElementById('my-container'),
  contentHeight: 3000, // Total scrollable height
  visibleHeight: 600,  // Height of the visible area
  onScroll: (scrollY) => {
    // Handle vertical scroll
    document.getElementById('content').style.transform = `translateY(-${scrollY}px)`;
  }
});

Programmatic Control

The signal-based implementation enables programmatic control of the scrollbars:

// Scroll to a specific position
horizontalScrollbar.scrollTo(500);

// Scroll to the middle
const middleX = (horizontalScrollbar.store.state.contentSize - horizontalScrollbar.store.state.visibleSize) / 2;
horizontalScrollbar.scrollTo(middleX);

// Get current scroll position
const currentPosition = horizontalScrollbar.scrollValue;

// Update content dimensions
horizontalScrollbar.setContentSize(3000);
verticalScrollbar.setContentSize(5000);

// Update visible dimensions (e.g., on window resize)
window.addEventListener('resize', () => {
  horizontalScrollbar.setVisibleSize(container.offsetWidth);
  verticalScrollbar.setVisibleSize(container.offsetHeight);
});

Advanced Signal Usage

The signals integration allows for more complex reactive behavior:

// Get direct access to the scroll signal
const scrollSignal = horizontalScrollbar.getScrollSignal();

// Connect to the signal for custom behavior
const cleanup = scrollSignal.connect((scrollValue) => {
  console.log('Horizontal scroll changed:', scrollValue);
  updateOtherElement(scrollValue);
});

// Clean up when done
cleanup();

// Create synchronized scrollbars
horizontalScrollbar.getScrollSignal().connect((scrollX) => {
  // Make vertical scrollbar follow horizontal scrollbar
  const ratio = scrollX / (horizontalScrollbar.store.state.contentSize - horizontalScrollbar.store.state.visibleSize);
  const targetY = ratio * (verticalScrollbar.store.state.contentSize - verticalScrollbar.store.state.visibleSize);
  verticalScrollbar.scrollTo(targetY);
});

Smooth Animations

Create smooth scroll animations by controlling the scrollbar programmatically:

function smoothScrollTo(scrollbar, targetPosition, duration = 500) {
  const startPosition = scrollbar.scrollValue;
  const distance = targetPosition - startPosition;
  const startTime = performance.now();
  
  function step(currentTime) {
    const elapsed = currentTime - startTime;
    const progress = Math.min(elapsed / duration, 1);
    const easeProgress = 1 - Math.pow(1 - progress, 3); // Cubic ease-out
    
    const currentPosition = startPosition + (distance * easeProgress);
    scrollbar.scrollTo(currentPosition);
    
    if (progress < 1) {
      requestAnimationFrame(step);
    }
  }
  
  requestAnimationFrame(step);
}

// Usage
smoothScrollTo(horizontalScrollbar, 1000, 800);

Styling

Using the included stylesheet

The package includes a basic stylesheet that you can import directly:

// Import the default styles
import '@rvanbaalen/custom-scroll/scrollbar.css';

Or include it via HTML if you're using a bundled version:

<link rel="stylesheet" href="path/to/node_modules/@rvanbaalen/custom-scroll/scrollbar.css">

Creating custom styles

You can also create your own custom styles. Add these to your CSS:

/* Track styles */
.custom-scrollbar-track {
  position: absolute;
  background: #f1f1f1;  /* Track background color */
  border-radius: 4px;   /* Rounded corners */
  z-index: 100;         /* Ensure proper stacking */
}

/* Thumb styles */
.custom-scrollbar-thumb {
  position: absolute;
  background: #888;     /* Thumb color */
  border-radius: 4px;   /* Rounded corners */
  cursor: pointer;      /* Change cursor on hover */
  z-index: 101;         /* Stack above the track */
}

.custom-scrollbar-thumb:hover {
  background: #555;     /* Darker color on hover */
}

/* Container needs to be positioned relatively or absolutely */
#my-container {
  position: relative;
  overflow: hidden;     /* Hide default scrollbars */
}

Themed scrollbars

You can create different themes or styles:

/* Dark theme */
.dark-theme .custom-scrollbar-track {
  background: #333;
}

.dark-theme .custom-scrollbar-thumb {
  background: #666;
}

.dark-theme .custom-scrollbar-thumb:hover {
  background: #999;
}

/* Minimal theme */
.minimal-theme .custom-scrollbar-track {
  background: transparent;
}

.minimal-theme .custom-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.2);
  border-radius: 10px;
}

.minimal-theme .custom-scrollbar-thumb:hover {
  background: rgba(0, 0, 0, 0.4);
}

Advanced styling techniques

For more control, you can add additional classes to the scrollbars:

// Add a custom class to the track and thumb elements
horizontalScrollbar.track.classList.add('custom-horizontal-track');
horizontalScrollbar.thumb.classList.add('custom-horizontal-thumb');

verticalScrollbar.track.classList.add('custom-vertical-track');
verticalScrollbar.thumb.classList.add('custom-vertical-thumb');

Then style these classes in your CSS:

/* Custom styling for horizontal scrollbar */
.custom-horizontal-track {
  height: 6px;           /* Thinner track */
  bottom: 0;             /* Position at bottom */
}

.custom-horizontal-thumb {
  background: linear-gradient(to right, #4568dc, #b06ab3); /* Gradient thumb */
}

/* Custom styling for vertical scrollbar */
.custom-vertical-track {
  width: 6px;            /* Thinner track */
  right: 0;              /* Position at right */
}

.custom-vertical-thumb {
  background: linear-gradient(to bottom, #4568dc, #b06ab3); /* Gradient thumb */
}

API Reference

HorizontalScrollbar

new HorizontalScrollbar({
  container: HTMLElement,    // Container element
  contentWidth: number,      // Total scrollable width
  visibleWidth: number,      // Width of the visible area
  onScroll: Function         // Callback function(scrollX)
})

VerticalScrollbar

new VerticalScrollbar({
  container: HTMLElement,    // Container element
  contentHeight: number,     // Total scrollable height
  visibleHeight: number,     // Height of the visible area
  onScroll: Function         // Callback function(scrollY)
})

Methods

Both scrollbar classes provide the following methods:

  • update(scrollValue): Updates the thumb position and size based on the current scroll value
  • scrollTo(value): Programmatically scrolls to a specific position
  • setContentSize(size): Updates the content size (width/height) and refreshes the scrollbar
  • setVisibleSize(size): Updates the visible size (width/height) and refreshes the scrollbar
  • getScrollSignal(): Returns the signal that emits when scrolling occurs

Properties

  • store.state.contentSize: The total scrollable size (width or height)
  • store.state.visibleSize: The visible size of the container (width or height)
  • scrollValue: The current scroll position

Use Cases

  • Custom data grids with fixed headers/columns
  • Design systems requiring consistent scrollbars across browsers
  • Interactive dashboards with custom UI components
  • Maps and visualization tools
  • Virtual scrolling implementations
  • Synchronized scrolling between multiple containers
  • Smooth scroll animations and effects

Browser Support

Works in all modern browsers that support ES6.

Development

  1. Clone the repository
  2. Install dependencies: npm install
  3. Start the development server: npm run dev
  4. Build for production: npm run build

Contributing

Contributions are welcome! If you have any suggestions, improvements, or bug fixes, please open an issue or submit a pull request.

License

Distributed under the MIT License. See the LICENSE file for more information.