Gathering detailed insights and metrics for react-scrollbars-custom
Gathering detailed insights and metrics for react-scrollbars-custom
Gathering detailed insights and metrics for react-scrollbars-custom
Gathering detailed insights and metrics for react-scrollbars-custom
The best React custom scrollbars component
npm install react-scrollbars-custom
Typescript
Module System
Node Version
NPM Version
93.2
Supply Chain
94.6
Quality
75.7
Maintenance
100
Vulnerability
100
License
TypeScript (91.95%)
HTML (5.37%)
JavaScript (2.69%)
Total Downloads
11,541,001
Last Day
2,232
Last Week
61,039
Last Month
248,299
Last Year
2,805,552
MIT License
851 Stars
653 Commits
73 Forks
8 Watchers
17 Branches
9 Contributors
Updated on Jun 29, 2025
Minified
Minified + Gzipped
Latest Version
4.1.1
Package Id
react-scrollbars-custom@4.1.1
Unpacked Size
241.90 kB
Size
43.95 kB
File Count
16
NPM Version
8.15.0
Node Version
18.7.0
Cumulative downloads
Total Downloads
Last Day
-0.4%
2,232
Compared to previous day
Last Week
-2%
61,039
Compared to previous week
Last Month
1.7%
248,299
Compared to previous month
Last Year
19.4%
2,805,552
Compared to previous year
3
1
30
1npm install react-scrollbars-custom 2# or via yarn 3yarn add react-scrollbars-custom
INSTALLATION NOTE:
This lib is written in ES6+ and delivering with both, transpiled and untranspiled versions:
main
field of package.json
is pointing to transpiled ES3-compatible version with CJS modules
resolution;module
field is pointing to transpiled ES3-compatible version with ES modules resolution;esnext
field is pointing to the ES6+ version with ES modules resolution;Depending on your targets you may have to use Webpack and/or
Babel to pull untranspiled version of package.
See some tips on wiring thing
up: https://2ality.com/2017/06/pkg-esnext.html
Underneath react-scrollbars-custom
uses requestAnimationFrame
loop, which check and update each
known scrollbar, and as result - scrollbars updates synchronised with browser's render flow.
The <Scrollbar />
component works out of the box, with only need of width
and height
to be
set, inline or via CSS;
1import { Scrollbar } from 'react-scrollbars-custom'; 2 3<Scrollbar style={{ width: 250, height: 250 }}> 4 <p>Hello world!</p> 5</Scrollbar>;
react-scrollbars-custom
is syntax-compatible with IE10, but you'll have to use polyfills - for
example @babel/polyfill.
Probably you'll wish to customize your scrollbars on your own way via CSS - then simply
pass noDefaultStyles
prop - it will prevent all inline styling from appear.
But some of styles will remain due to their need for proper component work.
One more pretty common need is to disable custom scrollbars and fallback to native ones, it can be
done by passing native
prop.
It'll change the generated markup:
1// scrollbar.scrollerElement 2<div class="ScrollbarsCustom native trackYVisible trackXVisible"> 3 // scrollbar.contentElement - the one that holds tour content 4 <div class="ScrollbarsCustom-Content">// YOUR CONTENT IS HERE</div> 5</div>
As you see here - now the root element has the scrollerElement
ref, but otherwise its treated as a
before (as holder). contentElement
behaves as it was before.
In some situations you may want to make the scrollbars block of variable sizes - just
pass translateContentSize*ToHolder
prop and component will automatically translate
corresponding contentElement
's sizes to the holderElement
.
If you are using default styles - it'll be handy to pass disableTracksWidthCompensation
props, to
avoid infinite shrinking when it's not supposed to.
Note: This wont work for native mode.
react-scrollbars-custom
supports RTL direction out of the box, you don't have to pass extra
parameters to make it work, it'll be detected automatically on first component's render. But you
still able to override it through the prop.
There are several things you have to know about:
isRtl
set to non-boolean value;rtl
property has priority over the style
or CSS properties;rtl
prop has not been set (undefined) - direction will be detected automatically according to
content element's CSS;rtl
prop is true
- direction: rtl;
style will be applied to hte content element;rtl
prop is false
- no style will be applied to holder;In some cases you may want to change the default className or tagName of elements or add extra
markup or whatever. For these purposes react-scrollbars-custom
made fully customizable.
You can do absolutely what ever you want y simply passing renderer SFC to the needed props.
IMPORTANT: Renderer will receive elementRef function that expect the DOM element's reference as first parameter.
Furthermore you have to pass the styles, cause they needed to proper component work.
1<Scrollbar 2 renderer={(props) => { 3 const { elementRef, ...restProps } = props; 4 return <span {...restProps} ref={elementRef} className="MyAwesomeScrollbarsHolder" />; 5 }} 6 wrapperProps={{ 7 renderer: (props) => { 8 const { elementRef, ...restProps } = props; 9 return <span {...restProps} ref={elementRef} className="MyAwesomeScrollbarsWrapper" />; 10 }, 11 }} 12 scrollerProps={{ 13 renderer: (props) => { 14 const { elementRef, ...restProps } = props; 15 return <span {...restProps} ref={elementRef} className="MyAwesomeScrollbarsScroller" />; 16 }, 17 }} 18 contentProps={{ 19 renderer: (props) => { 20 const { elementRef, ...restProps } = props; 21 return <span {...restProps} ref={elementRef} className="Content" />; 22 }, 23 }} 24 trackXProps={{ 25 renderer: (props) => { 26 const { elementRef, ...restProps } = props; 27 return <span {...restProps} ref={elementRef} className="TrackX" />; 28 }, 29 }} 30 trackYProps={{ 31 renderer: (props) => { 32 const { elementRef, ...restProps } = props; 33 return <span {...restProps} ref={elementRef} className="trackY" />; 34 }, 35 }} 36 thumbXProps={{ 37 renderer: (props) => { 38 const { elementRef, ...restProps } = props; 39 return <span {...restProps} ref={elementRef} className="ThUmBX" />; 40 }, 41 }} 42 thumbYProps={{ 43 renderer: (props) => { 44 const { elementRef, ...restProps } = props; 45 return <span {...restProps} ref={elementRef} className="tHuMbY" />; 46 }, 47 }} 48/>
1// scrollbar.holderElement 2<div class="ScrollbarsCustom trackYVisible trackXVisible"> 3 // scrollbar.wrapperElement - the one that hiding native scrollbars 4 <div class="ScrollbarsCustom-Wrapper"> 5 // scrollbar.scrollerElement - the one that actually has browser's scrollbars 6 <div class="ScrollbarsCustom-Scroller"> 7 // scrollbar.contentElement - the one that holds tour content 8 <div class="ScrollbarsCustom-Content">// YOUR CONTENT IS HERE</div> 9 </div> 10 </div> 11 // scrollbar.trackYElement 12 <div class="ScrollbarsCustom-Track ScrollbarsCustom-TrackY"> 13 // scrollbar.thumbYElement 14 <div class="ScrollbarsCustom-Thumb ScrollbarsCustom-ThumbY" /> 15 </div> 16 // scrollbar.trackXElement 17 <div class="ScrollbarsCustom-Track ScrollbarsCustom-TrackX"> 18 // scrollbar.thumbXElement 19 <div class="ScrollbarsCustom-Thumb ScrollbarsCustom-ThumbX" /> 20 </div> 21</div>
permanentScrollbar*
prop - trackYVisible
/trackXVisible
classnames are applied to the holder element.dragging
classname.rtl
classname will be added to the holder element.removeTrackXWhenNotUsed
/removeTrackYWhenNotUsed
/removeTracksWhenNotUsed
props to the component. Respective tracks will not be rendered if it is
unnecessary.You can pass any HTMLDivElement props to the component - they'll be respectfully passed to the holder element/renderer.
createContext :boolean
= undefined
Whether to create context that will contain scrollbar instance reference.
rtl :boolean
= undefined
true
- set content's direction RTL, false
- LTR, undefined
- autodetect according content's
style.
native :boolean
= undefined
Do not use custom scrollbars, use native ones instead.
mobileNative :boolean
= undefined
As native
but enables only on mobile devices (actually when the scrollbarWidth
is 0).
momentum :boolean
= true
Whether to use momentum scrolling, suitable for iOS (will add -webkit-overflow-scrolling: touch
to
the content element).
noDefaultStyles :boolean
= undefined
Whether to use default visual styles.
Note: Styles needed to proper component work will be passed regardless of this option.
disableTracksMousewheelScrolling :boolean
= undefined
Disable content scrolling while preforming a wheel event over the track.
disableTrackXMousewheelScrolling :boolean
= undefined
Disable content scrolling while preforming a wheel event over the track.
disableTrackYMousewheelScrolling :boolean
= undefined
Disable content scrolling while preforming a wheel event over the track.
disableTracksWidthCompensation :boolean
= undefined
Disable both vertical and horizontal wrapper indents that added in order to not let tracks overlay
content.
Note: Works only with default styles enabled.
disableTrackXWidthCompensation :boolean
= undefined
Disable horizontal wrapper indents that added in order to not let horizontal track overlay content.
Note: Works only with default styles enabled.
disableTrackYWidthCompensation :boolean
= undefined
Disable vertical wrapper indents that added in order to not let vertical track overlay content.
Note: Works only with default styles enabled.
minimalThumbSize :number
= 30
Minimal size of both, vertical and horizontal thumbs. This option has priority
to minimalThumbXSize
/minimalThumbYSize
props.
maximalThumbSize :number
= undefined
Maximal size of both, vertical and horizontal thumbs. This option has priority
to maximalThumbXSize
/maximalThumbYSize
props.
minimalThumbXSize :number
= undefined
Minimal size of horizontal thumb.
maximalThumbXSize :number
= undefined
Maximal size of horizontal thumb.
minimalThumbYSize :number
= undefined
Minimal size of vertical thumb.
maximalThumbYSize :number
= undefined
Maximal size of vertical thumb.
noScroll :boolean
= undefined
Whether to disable both vertical and horizontal scrolling.
noScrollX :boolean
= undefined
Whether to disable horizontal scrolling.
noScrollY :boolean
= undefined
Whether to disable vertical scrolling.
permanentTracks :boolean
= undefined
Whether to display both tracks regardless of scrolling ability.
permanentTrackX :boolean
= undefined
Whether to display horizontal track regardless of scrolling ability.
permanentTrackY :boolean
= undefined
Whether to display vertical track regardless of scrolling ability.
removeTracksWhenNotUsed :boolean
= undefined
Whether to remove both vertical and horizontal tracks if scrolling is not possible/blocked and
tracks are not permanent.
removeTrackYWhenNotUsed :boolean
= undefined
Whether to remove vertical track if scrolling is not possible/blocked and tracks are not permanent.
removeTrackXWhenNotUsed :boolean
= undefined
Whether to remove horizontal track if scrolling is not possible/blocked and tracks are not
permanent.
translateContentSizesToHolder :boolean
= undefined
Pass content's scrollHeight
and scrollWidth
values to the holder's height
and width
styles. Not working with native
behavior.
translateContentSizeYToHolder :boolean
= undefined
Pass content's scrollHeight
values to the holder's height
style. Not working with native
behavior.
translateContentSizeXToHolder :boolean
= undefined
Pass content's scrollWidth
values to the holder's width
style. Not working with native
behavior.
trackClickBehavior :string
= "jump"
The way scrolling behaves while user clicked the track:
scrollbarWidth :number
= undefined
Scrollbar width value needed to proper native scrollbars hide. While undefined
it is detected
automatically (once per module require).
This prop is needed generally for testing purposes.
fallbackScrollbarWidth :number
= 20
This value will be used in case of falsy scrollbarWidth
prop. E.g. it is used for mobile devices,
because it is impossible to detect their real scrollbar width (due to their absolute positioning).
scrollTop :number
= undefined
Prop that allow you to set vertical scroll.
scrollLeft :number
= undefined
Prop that allow you to set horizontal scroll.
scrollDetectionThreshold :number
= 100
Amount of seconds after which scrolling will be treated as completed and scrollStop
event emitted.
elementRef :function(ref: Scrollbar)
= undefined
Function that receive the scrollbar instance as 1st parameter.
renderer :SFC
= undefined
SFC used to render the holder. More about renderers usage.
wrapperProps :object
= {}
Here you can pass any props for wrapper, which is usually HTMLDivElement plus elementRef
props
which behaves as holder's elementRef
prop.
contentProps :object
= {}
Here you can pass any props for content, which is usually HTMLDivElement plus elementRef
props
which behaves as holder's elementRef
prop.
trackXProps :object
= {}
Here you can pass any props for trackX, which is usually HTMLDivElement plus elementRef
props
which behaves as holder's elementRef
prop.
trackYProps :object
= {}
Here you can pass any props for trackY, which is usually HTMLDivElement plus elementRef
props
which behaves as holder's elementRef
prop.
thumbXProps :object
= {}
Here you can pass any props for thumbX, which is usually HTMLDivElement plus elementRef
props
which behaves as holder's elementRef
prop.
thumbYProps :object
= {}
Here you can pass any props for thumbY, which is usually HTMLDivElement plus elementRef
props
which behaves as holder's elementRef
prop.
onUpdate :function(scrollValues: ScrollState, prevScrollValues: ScrollState)
= undefined
Function called each time any of scroll values changed and component performed an update. It is
called after component's update.
onScroll :function(scrollValues: ScrollState, prevScrollValues: ScrollState)
= undefined
Function called each time scrollTop or scrollLeft has changed. It is called after component's update
and even if scrollTop/scrollLeft has been changed through the code (not by user).
onScrollStart :function(scrollValues: ScrollState)
= undefined
Callback that called immediately when user started scrolling (no matter how, thumb dragging,
keyboard, mousewheel and etc.).
onScrollStop :function(scrollValues: ScrollState)
= undefined
Callback that called after props.scrollDetectionThreshold
milliseconds after last scroll event.
eventEmitter :Emittr
Event emitter that allow you to add events handler for cases when you access Scrollbars through
context
holderElement :HTMLDivElement | null
Holder DOM element reference or null if element was not rendered
wrapperElement :HTMLDivElement | null
Wrapper DOM element reference or null if element was not rendered
scrollerElement :HTMLDivElement | null
Scroller DOM element reference or null if element was not rendered
contentElement :HTMLDivElement | null
Content DOM element reference or null if element was not rendered
trackXElement :HTMLDivElement | null
Horizontal track DOM element reference or null if element was not rendered
trackYElement :HTMLDivElement | null
Vertical track DOM element reference or null if element was not rendered
thumbXElement :HTMLDivElement | null
Horizontal thumb DOM element reference or null if element was not rendered
thumbYElement :HTMLDivElement | null
Vertical thumb DOM element reference or null if element was not rendered
(get|set) scrollTop :number
Content's element scroll top
(get|set) scrollLeft :number
Content's element scroll left
(get) scrollHeight :number
Content's element scroll height
(get) scrollWidth :number
Content's element scroll width
(get) clientHeight :number
Content's element client height
(get) clientWidth :number
Content's element client width
getScrollState(force:boolean = false) :plain object
Current scroll-related values, if force
parameter is falsy - returns cached value which updated
with RAF loop
Returned values:
1type ScrollState = { 2 /** 3 * @description Content's native clientHeight parameter 4 */ 5 clientHeight: number; 6 /** 7 * @description Content's native clientWidth parameter 8 */ 9 clientWidth: number; 10 /** 11 * @description Content's native scrollHeight parameter 12 */ 13 scrollHeight: number; 14 /** 15 * @description Content's native scrollWidth parameter 16 */ 17 scrollWidth: number; 18 /** 19 * @description Content's native scrollTop parameter 20 */ 21 scrollTop: number; 22 /** 23 * @description Content's native scrollLeft parameter 24 */ 25 scrollLeft: number; 26 /** 27 * @description Indicates whether vertical scroll blocked via properties 28 */ 29 scrollYBlocked: boolean; 30 /** 31 * @description Indicates whether horizontal scroll blocked via properties 32 */ 33 scrollXBlocked: boolean; 34 /** 35 * @description Indicates whether the content overflows vertically and scrolling not blocked 36 */ 37 scrollYPossible: boolean; 38 /** 39 * @description Indicates whether the content overflows horizontally and scrolling not blocked 40 */ 41 scrollXPossible: boolean; 42 /** 43 * @description Indicates whether vertical track is visible 44 */ 45 trackYVisible: boolean; 46 /** 47 * @description Indicates whether horizontal track is visible 48 */ 49 trackXVisible: boolean; 50 /** 51 * @description Indicates whether display direction is right-to-left 52 */ 53 isRTL?: boolean; 54 55 /** 56 * @description Pages zoom level - it affects scrollbars 57 */ 58 zoomLevel: number; 59};
scrollToTop() :this
Scroll to the very top border of scrollable area
scrollToLeft() :this
Scroll to the very left border of scrollable area
scrollToBottom() :this
Scroll to the very bottom border of scrollable area
scrollToRight() :this
Scroll to the very right border of scrollable area
scrollTo(x?: number, y?: number) :this
Set the current scroll at given coordinates. If any value is undefined
it'll be left as is.
centerAt(x?: number, y?: number) :this
Center viewport at given coordinates. If any value is undefined
it'll be left as is.
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
57 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-06-23
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More