react-custom-scrollbars-2

Cross-browser, cross-device scrollbars for React with native scrolling, full style customization, and universal (SSR-safe) rendering.

Library
npm
v4.5.0
162stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
39/100Needs Attention
Development Activity0
Maintenance0
Community76
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
60/100Good
Architecture60
Code Quality55
Innovation60
Learning Curve65

react-custom-scrollbars-2 renders a <Scrollbars> wrapper component that gives every browser and device consistent, fully customizable scrollbars while preserving native scroll physics — including momentum scrolling and touch support on mobile. It is a community-maintained continuation of the original react-custom-scrollbars package, created specifically to keep bug fixes flowing after the original stalled.

Out of the box it needs no configuration beyond a width/height style, but every visual piece — the view, the horizontal and vertical tracks, and their thumbs — can be swapped out via render-prop-style functions, and scroll state is exposed through callbacks (onScroll, onScrollFrame, onScrollStart, onScrollStop, onUpdate) plus an imperative ref API (scrollTop, scrollToBottom, getValues, etc.) for programmatic control.

What You Get

  • A single <Scrollbars> component that wraps any content and adds custom horizontal/vertical scrollbars with sane defaults
  • Auto-hide and auto-height modes for scrollbars that appear only on interaction or size themselves to content
  • Full customization of the view, track, and thumb elements via render-prop functions
  • An imperative ref API (scrollTop, scrollLeft, scrollToBottom, getValues, etc.) for programmatic scroll control
  • Universal-rendering support so the component mounts safely in server-rendered React apps
  • Bundled TypeScript type definitions (index.d.ts) alongside the CommonJS build

Common Use Cases

  • Styling scrollbars inside custom modals, dropdowns, or sidebars to match a design system instead of relying on inconsistent OS-native scrollbars
  • Building chat panels, code viewers, or feeds that need auto-hiding scrollbars and precise scroll-position callbacks
  • Rendering scrollable regions in server-rendered (SSR) React apps where native scrollbar behavior differs between server and client
  • Programmatically controlling scroll position (e.g. auto-scroll-to-bottom in a chat log) via the component’s ref API

Under The Hood

Architecture The entire component lives in a single ~650-line class, src/Scrollbars/index.js, which owns DOM refs to the container, view, and track/thumb elements; wires up scroll/resize/mouse listeners itself in addListeners/removeListeners; and drives visual updates through a requestAnimationFrame loop (via the raf/caf helpers) rather than React re-renders for scroll-position changes. Style computation is factored out into src/Scrollbars/styles.js, and the default DOM elements for the view/tracks/thumbs live in src/Scrollbars/defaultRenderElements.js, each overridable through render* props — the component’s only real extension point, since there is no dependency injection or plugin system. Small src/utils/* helpers (getScrollbarWidth, getInnerWidth/getInnerHeight, isString) support cross-browser measurement quirks. Because one class owns mounting, imperative scroll methods, and internal state together, most behavioral changes touch the same file directly rather than being isolated to a layer.

Tech Stack Built against React as a peer dependency (supporting the very wide ^0.14.0 through ^18.0.0 range) with prop-types for runtime prop validation, dom-css for applying computed inline styles, and raf for a cross-browser requestAnimationFrame/cancelAnimationFrame shim. The build pipeline is Babel 6 (es2015/react/stage-1 presets) compiling src/ to a CommonJS lib/ output, plus a separate Webpack 1 build producing UMD bundles (dist/react-custom-scrollbars.js and a minified variant) for script-tag consumption via unpkg. Hand-written index.d.ts type definitions ship alongside the JS build rather than being generated from source.

Code Quality A dedicated test/ directory exercises resizing, dragging, auto-hide, auto-height, flexbox layouts, universal/SSR mounting, and getter/setter behavior using Karma, Mocha, and a real Chrome launcher, with coverage collection via isparta (the README claims 100% coverage historically). Error handling is largely implicit — the code leans on DOM APIs and guards with simple conditionals rather than try/catch — and typing is limited to prop-types plus the separately maintained .d.ts file, not compile-time TypeScript. ESLint (airbnb config) is wired via an npm script. The toolchain itself (Babel 6, Webpack 1, Karma, Travis CI) is dated and the repo shows low recent commit activity, consistent with a fork maintained mainly for bug fixes rather than active feature development.

API Design Default usage requires almost no boilerplate — wrap content in <Scrollbars style={{ width, height }}> and get working custom scrollbars with auto-hide and universal-rendering options available as simple boolean props. Every visual piece can be replaced via render* function props without forking the component, and scroll state is observable through a consistent set of onScroll*/onUpdate callbacks plus an imperative ref API. Documentation is thorough for a small library, with dedicated docs/API.md, docs/usage.md, and docs/customization.md files covering the full prop and method surface.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search