Skip to content

dev-ahmedmahmoud/react-custom-scrollbars

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

react-custom-scrollbars

npm npm version npm downloads

Modern React scrollbars component with TypeScript support and React 19 compatibility.

✨ Features

  • πŸš€ Modern React Hooks - Built with React hooks and TypeScript
  • πŸ“± Native mobile scrolling - Native scrollbars for mobile devices
  • 🎨 Fully customizable - Complete control over scrollbar appearance
  • πŸ”„ Auto hide - Configurable auto-hide functionality
  • πŸ“ Auto height - Dynamic height based on content
  • 🌐 Universal - SSR compatible (runs on client & server)
  • ⚑ 60fps performance - Smooth scrolling with requestAnimationFrame
  • 🎯 Zero dependencies - No external dependencies in production
  • πŸ“˜ TypeScript ready - Full TypeScript support with proper types
  • βœ… Well tested - Comprehensive test coverage

πŸ“¦ Installation

npm package

npm install @dev-ahmed-mahmoud/react-custom-scrollbars

Package Info:

  • πŸ“‹ Package: @dev-ahmed-mahmoud/react-custom-scrollbars
  • 🌐 Registry: npm
  • πŸ“Š Bundle size: ~18KB (5.4KB gzipped)
  • 🏷️ License: MIT

πŸš€ Usage

Basic Example

import React from 'react'
import { Scrollbars } from '@dev-ahmed-mahmoud/react-custom-scrollbars'

function App() {
  return (
    <Scrollbars style={{ width: 500, height: 300 }}>
      <p>Some great content...</p>
    </Scrollbars>
  )
}

Advanced Example with TypeScript

import React, { useRef } from 'react'
import { Scrollbars, ScrollbarsRef, ScrollValues } from '@dev-ahmed-mahmoud/react-custom-scrollbars'

function CustomScrollbars() {
  const scrollbars = useRef<ScrollbarsRef>(null)

  const handleScrollFrame = (values: ScrollValues) => {
    const { top } = values
    if (top > 0.8) {
      console.log('Near bottom!')
    }
  }

  const scrollToTop = () => {
    scrollbars.current?.scrollToTop()
  }

  return (
    <div>
      <button onClick={scrollToTop}>Scroll to top</button>
      <Scrollbars
        ref={scrollbars}
        onScrollFrame={handleScrollFrame}
        renderThumbVertical={({ style, ...props }) => (
          <div
            style={{
              ...style,
              backgroundColor: '#007bff',
              borderRadius: '3px',
            }}
            {...props}
          />
        )}
        style={{ width: 500, height: 300 }}
      >
        <div style={{ padding: 20 }}>
          {Array.from({ length: 50 }, (_, i) => (
            <p key={i}>Content line {i + 1}</p>
          ))}
        </div>
      </Scrollbars>
    </div>
  )
}

πŸ“š API Reference

Props

Prop Type Default Description
onScroll (event: Event) => void - Event handler for scroll events
onScrollFrame (values: ScrollValues) => void - Runs inside the animation frame
onScrollStart () => void - Called when scrolling starts
onScrollStop () => void - Called when scrolling stops
onUpdate (values: ScrollValues) => void - Called when component updates
renderView (props: RenderElementProps) => ReactElement - Custom view component
renderTrackHorizontal (props: RenderElementProps) => ReactElement - Custom horizontal track
renderTrackVertical (props: RenderElementProps) => ReactElement - Custom vertical track
renderThumbHorizontal (props: RenderElementProps) => ReactElement - Custom horizontal thumb
renderThumbVertical (props: RenderElementProps) => ReactElement - Custom vertical thumb
hideTracksWhenNotNeeded boolean false Hide tracks when content doesn't overflow
thumbSize number - Fixed thumb size in px
thumbMinSize number 30 Minimum thumb size in px
autoHide boolean false Enable auto-hide mode
autoHideTimeout number 1000 Hide delay in ms
autoHideDuration number 200 Duration for hide animation in ms
autoHeight boolean false Enable auto-height mode
autoHeightMin number | string 0 Minimum height for auto-height mode
autoHeightMax number | string 200 Maximum height for auto-height mode
universal boolean false Enable universal/SSR rendering
tagName string 'div' Container element tag name

Ref Methods

The component provides imperative methods through refs:

interface ScrollbarsRef {
  getScrollLeft(): number
  getScrollTop(): number
  getScrollWidth(): number
  getScrollHeight(): number
  getClientWidth(): number
  getClientHeight(): number
  getValues(): ScrollValues
  scrollLeft(left?: number): void
  scrollTop(top?: number): void
  scrollToLeft(): void
  scrollToTop(): void
  scrollToRight(): void
  scrollToBottom(): void
}

πŸ› οΈ Development

# Install dependencies
npm install

# Run development server
npm run dev

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Build for production
npm run build

# Lint code
npm run lint

# Format code
npm run format

πŸ“ Migration from v4

This is a major version with breaking changes:

Breaking Changes

  • Node.js 18+ required
  • React 18+ required
  • Component converted to hooks (no more class component)
  • TypeScript first (JavaScript still supported)
  • ES modules only (no UMD build)
  • Removed deprecated props and methods

Methods (via ref)

Method Description
scrollTop(top: number) Scroll to specific top position
scrollLeft(left: number) Scroll to specific left position
scrollToTop() Scroll to top
scrollToBottom() Scroll to bottom
scrollToLeft() Scroll to left
scrollToRight() Scroll to right
getScrollLeft() Get current scrollLeft value
getScrollTop() Get current scrollTop value
getScrollWidth() Get scrollable width
getScrollHeight() Get scrollable height
getClientWidth() Get view client width
getClientHeight() Get view client height
getValues() Get current scroll values object

πŸ“‹ Requirements

  • Node.js: 20.0.0 or higher
  • React: 18.0.0 or higher (React 19 supported)
  • TypeScript: 5.8+ (optional, but recommended)

πŸ“– Documentation

πŸš€ Migration from v4.x

Version 5.0 maintains API compatibility while modernizing the internals:

// βœ… Your existing v4 code mostly works as-is
<Scrollbars
  style={{ width: 500, height: 300 }}
  autoHide
  autoHideTimeout={1000}
  onScrollStart={() => console.log('Started')}
  onScrollStop={() => console.log('Stopped')}
>
  {content}
</Scrollbars>

Key Changes:

  • Now requires React 18+ and Node.js 20+
  • Written in TypeScript with built-in types
  • Modern hooks-based implementation
  • ES modules only (no CommonJS)
  • Smaller bundle size and better performance

See the complete upgrade guide for details.

πŸ”„ Changelog

See CHANGELOG.md for version history and breaking changes.

🀝 Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

πŸ“„ License

MIT Β© Malte Wessel (original author)

v5.0 modernization by Ahmed Mahmoud

About

Modern React scrollbars component with TypeScript support and React 19 compatibility. Hooks-based implementation with zero dependencies.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Languages

  • TypeScript 83.4%
  • JavaScript 16.6%