react-custom-scrollbars vs react-scrollbars-custom
Custom Scrollbar Implementation in React Applications
react-custom-scrollbarsreact-scrollbars-custom

Custom Scrollbar Implementation in React Applications

react-custom-scrollbars and react-scrollbars-custom are both React components designed to replace native browser scrollbars with customizable, cross-browser consistent alternatives. react-custom-scrollbars was one of the earliest and most popular solutions, offering a simple API to style scrollbars across different operating systems. react-scrollbars-custom emerged later as a modern alternative, focusing on better TypeScript support, more flexible styling options, and improved handling of native scrollbar behavior without hiding it completely. Both aim to solve the inconsistency of native scrollbars across Windows, macOS, and Linux, but they differ in their approach to DOM structure, performance, and long-term maintenance.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
react-custom-scrollbars03,221-2179 years agoMIT
react-scrollbars-custom0860248 kB67-MIT

Custom Scrollbars in React: react-custom-scrollbars vs react-scrollbars-custom

Consistent scrollbar styling across browsers is a common design requirement, but native scrollbars vary wildly between Windows, macOS, and Linux. react-custom-scrollbars and react-scrollbars-custom both address this by wrapping content in custom DOM structures that mimic scrolling behavior. However, their age, maintenance status, and technical implementation differ significantly. Let's look at how they handle rendering, styling, and React integration.

πŸ› οΈ Maintenance and React Compatibility

react-custom-scrollbars is effectively deprecated.

  • The repository has seen little to no activity in recent years.
  • It relies on older React patterns (like findDOMNode) that trigger warnings in Strict Mode.
  • It does not officially support modern React features like Concurrent Mode.
// react-custom-scrollbars: Legacy patterns
import { Scrollbars } from 'react-custom-scrollbars';

// May trigger warnings in React 18+ Strict Mode
<Scrollbars style={{ width: 500, height: 300 }}>
  <div>Content</div>
</Scrollbars>

react-scrollbars-custom is actively maintained (relative to the alternative).

  • Built with TypeScript from the ground up.
  • Avoids deprecated React APIs.
  • Better suited for modern React 18+ applications.
// react-scrollbars-custom: Modern patterns
import { Scrollbars } from 'react-scrollbars-custom';

// Compatible with React 18+ Strict Mode
<Scrollbars style={{ width: 500, height: 300 }}>
  <div>Content</div>
</Scrollbars>

🎨 Styling and Customization Approach

react-custom-scrollbars uses inline styles and specific class names.

  • You pass style objects directly to props.
  • Customizing the thumb or track requires targeting specific internal classes.
  • Limited flexibility for complex themes without CSS overrides.
// react-custom-scrollbars: Inline styles
<Scrollbars 
  style={{ width: 500, height: 300 }}
  thumbSize={{ width: 8, height: 8 }}
  renderThumb={(props) => <div {...props} style={{ ...props.style, backgroundColor: '#333' }} />}
>
  <div>Content</div>
</Scrollbars>

react-scrollbars-custom uses a CSS-class-based system with a wrapper.

  • It applies a wrapper class you can target with CSS or CSS-in-JS.
  • Offers more granular control over elements like track, thumb, and corner.
  • Supports props to disable native scrollbars entirely or style them.
// react-scrollbars-custom: CSS class targeting
<Scrollbars 
  style={{ width: 500, height: 300 }}
  renderer={({ elementRef, ...restProps }) => (
    <div ref={elementRef} {...restProps} className="my-custom-scroll" />
  )}
>
  <div>Content</div>
</Scrollbars>
/* Targeting internal elements via CSS */
.my-custom-scroll .rsb__thumb {
  background-color: #333;
  border-radius: 4px;
}

πŸ“ DOM Structure and Layout

react-custom-scrollbars creates a fixed nested structure.

  • It wraps content in multiple divs to simulate the scrollbar track and thumb.
  • This can interfere with CSS layouts like Flexbox or Grid if not accounted for.
  • The content container is absolutely positioned, which can cause issues with dynamic height.
// react-custom-scrollbars: Fixed structure
// Internally renders:
// <div> (wrapper)
//   <div> (content container - absolute)
//     {children}
//   </div>
//   <div> (scrollbar elements)
// </div>

react-scrollbars-custom allows more control over the element refs.

  • You can pass refs to the underlying DOM nodes more easily.
  • Better handling of dynamic content resizing.
  • Reduces layout shift issues compared to the older package.
// react-scrollbars-custom: Ref forwarding
const scrollRef = useRef(null);

<Scrollbars 
  ref={scrollRef}
  style={{ width: 500, height: 300 }}
>
  <div>Content</div>
</Scrollbars>

// Access underlying methods
scrollRef.current.scrollTop(100);

⚑ Performance and Native Behavior

react-custom-scrollbars hides native scrollbars completely.

  • It prevents native scrolling events and simulates them via JS.
  • This can lead to janky scrolling on touch devices or high-DPI screens.
  • Momentum scrolling (inertial scroll) is often lost on mobile.
// react-custom-scrollbars: JS-driven scroll
// Relies on listening to wheel/touch events and updating state
// Can feel less smooth on touch devices
<Scrollbars onScroll={(e) => console.log(e)}>
  <div>Content</div>
</Scrollbars>

react-scrollbars-custom attempts to preserve native behavior where possible.

  • It can style native scrollbars instead of replacing them entirely (via CSS).
  • If replacing, it tries to minimize JS intervention for better performance.
  • Better support for touch devices and momentum scrolling.
// react-scrollbars-custom: Native styling option
// Can use CSS to style native scrollbars instead of JS replacement
<Scrollbars 
  style={{ width: 500, height: 300 }}
  disableNativeScrollbar={false} // Keeps native, styles it
>
  <div>Content</div>
</Scrollbars>

🌐 Browser Support and CSS

react-custom-scrollbars relies heavily on JS for cross-browser consistency.

  • Works everywhere JS runs, but feels inconsistent on different OS.
  • Does not leverage modern CSS scrollbar pseudo-elements effectively.
/* react-custom-scrollbars: Limited CSS hook usage */
.scrollbar-track {
  /* Must be applied via props or global CSS overrides */
}

react-scrollbars-custom leverages modern CSS where possible.

  • Can fall back to native CSS styling for browsers that support it (Chrome, Edge).
  • Reduces JS overhead for browsers with good native scrollbar styling support.
/* react-scrollbars-custom: Can combine with native CSS */
::-webkit-scrollbar {
  width: 8px;
}
::-webkit-scrollbar-thumb {
  background: #333;
}

🀝 Similarities: Shared Ground

Despite their differences, both packages solve the same core problem with similar high-level APIs.

1. πŸ“¦ Component-Based API

  • Both export a main <Scrollbars> component.
  • Both accept style, className, and children props.
// Both packages share this basic usage pattern
<Scrollbars style={{ height: 400 }}>
  <div>Long content...</div>
</Scrollbars>

2. πŸ”„ Scroll Event Handling

  • Both provide onScroll callbacks.
  • Both allow programmatic scrolling via refs.
// Both support programmatic control
const ref = useRef();
ref.current.scrollTop(100); // Works in both (with slight API diffs)

3. πŸ“ Auto-Height and Auto-Width

  • Both support props to automatically size the container based on content.
  • Useful for chat windows or dynamic lists.
// Both support auto-sizing
<Scrollbars autoHeight autoHeightMax={300}>
  <div>Content</div>
</Scrollbars>

4. πŸŽ›οΈ Render Props for Customization

  • Both allow you to render custom components for the thumb, track, and view.
  • Enables branding and custom UI integration.
// Both allow custom thumb rendering
<Scrollbars renderThumb={(props) => <div {...props} className="custom-thumb" />}>
  <div>Content</div>
</Scrollbars>

5. πŸ“± Universal Rendering (SSR)

  • Both claim to support Server-Side Rendering.
  • react-scrollbars-custom handles hydration mismatches better in practice.
// Both can be rendered on server
// But react-scrollbars-custom reduces hydration warnings

πŸ“Š Summary: Key Similarities

FeatureShared by Both
Core Component<Scrollbars> wrapper
Propsstyle, className, onScroll
SizingautoHeight, autoWidth
CustomizationrenderThumb, renderTrack
Scroll ControlRef-based methods (scrollTop)
SSRSupported (with caveats)

πŸ†š Summary: Key Differences

Featurereact-custom-scrollbarsreact-scrollbars-custom
Maintenance❌ Deprecated / Unmaintainedβœ… Actively Maintained
React Version⚠️ Legacy (Strict Mode warnings)βœ… Modern (React 18+ ready)
TypeScript❌ Community types onlyβœ… Built-in TS support
Scroll EngineJS SimulationHybrid (Native + JS)
Touch Support⚠️ Poor momentum scrollingβœ… Better touch handling
StylingInline stylesCSS Classes + Inline

πŸ’‘ The Big Picture

react-custom-scrollbars is a legacy solution πŸ•°οΈ. It served the community well for many years but has fallen behind modern React standards. Using it today introduces technical debt, potential bugs in Strict Mode, and lack of future support. Only use it if you are stuck maintaining an old app.

react-scrollbars-custom is the modern successor πŸ› οΈ. It offers better TypeScript integration, respects native browser behaviors more, and is safer for new projects. However, before adding any dependency, consider if modern CSS (::-webkit-scrollbar or scrollbar-width) can solve your design needs without JS overhead.

Final Thought: For new projects, prefer react-scrollbars-custom if JS control is strictly required. Otherwise, lean on native CSS scrollbar styling for better performance and less bundle weight. Avoid react-custom-scrollbars entirely in greenfield development.

How to Choose: react-custom-scrollbars vs react-scrollbars-custom

  • react-custom-scrollbars:

    Choose react-custom-scrollbars only if you are maintaining a legacy codebase that already depends on it and migration is too costly. It is widely considered deprecated and unmaintained, with known issues regarding modern React versions (like Strict Mode) and server-side rendering. Do not start new projects with this package as it lacks active support and may break with future React updates.

  • react-scrollbars-custom:

    Choose react-scrollbars-custom if you need a actively maintained solution with better TypeScript definitions and more control over the scrollbar appearance without completely replacing the native engine. It is suitable for projects that require consistent styling across browsers but still want to leverage native scrolling performance where possible. However, evaluate if you actually need a custom scrollbar, as modern CSS solutions might suffice for simpler use cases.

README for react-custom-scrollbars

react-custom-scrollbars

npm npm version npm downloads

  • frictionless native browser scrolling
  • native scrollbars for mobile devices
  • fully customizable
  • auto hide
  • auto height
  • universal (runs on client & server)
  • requestAnimationFrame for 60fps
  • no extra stylesheets
  • well tested, 100% code coverage

Demos Β· Documentation

Installation

npm install react-custom-scrollbars --save

This assumes that you’re using npm package manager with a module bundler like Webpack or Browserify to consume CommonJS modules.

If you don’t yet use npm or a modern module bundler, and would rather prefer a single-file UMD build that makes ReactCustomScrollbars available as a global object, you can grab a pre-built version from unpkg. We don’t recommend this approach for any serious application, as most of the libraries complementary to react-custom-scrollbars are only available on npm.

Usage

This is the minimal configuration. Check out the Documentation for advanced usage.

import { Scrollbars } from 'react-custom-scrollbars';

class App extends Component {
  render() {
    return (
      <Scrollbars style={{ width: 500, height: 300 }}>
        <p>Some great content...</p>
      </Scrollbars>
    );
  }
}

The <Scrollbars> component is completely customizable. Check out the following code:

import { Scrollbars } from 'react-custom-scrollbars';

class CustomScrollbars extends Component {
  render() {
    return (
      <Scrollbars
        onScroll={this.handleScroll}
        onScrollFrame={this.handleScrollFrame}
        onScrollStart={this.handleScrollStart}
        onScrollStop={this.handleScrollStop}
        onUpdate={this.handleUpdate}
        renderView={this.renderView}
        renderTrackHorizontal={this.renderTrackHorizontal}
        renderTrackVertical={this.renderTrackVertical}
        renderThumbHorizontal={this.renderThumbHorizontal}
        renderThumbVertical={this.renderThumbVertical}
        autoHide
        autoHideTimeout={1000}
        autoHideDuration={200}
        autoHeight
        autoHeightMin={0}
        autoHeightMax={200}
        thumbMinSize={30}
        universal={true}
        {...this.props}>
    );
  }
}

All properties are documented in the API docs

Examples

Run the simple example:

# Make sure that you've installed the dependencies
npm install
# Move to example directory
cd react-custom-scrollbars/examples/simple
npm install
npm start

Tests

# Make sure that you've installed the dependencies
npm install
# Run tests
npm test

Code Coverage

# Run code coverage. Results can be found in `./coverage`
npm run test:cov

License

MIT