How to Create a Custom Scrollbar in React
Scrollbars are one of the most overlooked UI elements in web applications. The default browser scrollbar often doesn’t match the design language of modern apps.
In this guide, you’ll learn how to create a custom scrollbar in React, ranging from simple CSS styling to a fully custom React-powered scrollbar component.
We’ll cover:
Styling the native scrollbar with CSS
Creating a reusable custom scrollbar component in React
Handling scroll synchronization and thumb dragging
- Styling the Native Scrollbar (Quick Method)
The easiest way to customize scrollbars in React is with CSS pseudo-elements.
This works in Chrome, Edge, and Safari using ::-webkit-scrollbar.
Example /* scrollbar width */ ::-webkit-scrollbar { width: 10px; }
/* scrollbar track */ ::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 10px; }
/* scrollbar thumb */ ::-webkit-scrollbar-thumb { background: #888; border-radius: 10px; }
/* hover effect */ ::-webkit-scrollbar-thumb:hover { background: #555; }
Then apply it to your scroll container.
function ScrollContainer() { return (
Item {i}
))} ); } Pros
Very simple
No JavaScript needed
Good for quick styling
Cons
Limited control
Not fully cross-browser
Cannot fully customize behavior
For full control, we need to build a custom scrollbar component.
- Building a Custom Scrollbar Component in React
Instead of styling the browser scrollbar, we hide it and build our own scrollbar UI.
Concept
The custom scrollbar consists of three parts:
Container — wrapper component
Scrollable Content
Scrollbar Track + Thumb
Project Structure components/ CustomScrollbar.jsx CustomScrollbar.css 3. Creating the Custom Scrollbar Component CustomScrollbar.jsx import { useRef, useState, useEffect } from "react"; import "./CustomScrollbar.css";
export default function CustomScrollbar({ children }) { const contentRef = useRef(null); const [thumbHeight, setThumbHeight] = useState(20); const [thumbTop, setThumbTop] = useState(0);
useEffect(() => { const el = contentRef.current;
const updateThumb = () => {
const { scrollHeight, clientHeight, scrollTop } = el;
const height = Math.max(
(clientHeight / scrollHeight) * clientHeight,
20
);
const top = (scrollTop / scrollHeight) * clientHeight;
setThumbHeight(height);
setThumbTop(top);
};
updateThumb();
el.addEventListener("scroll", updateThumb);
return () => el.removeEventListener("scroll", updateThumb);
}, []);
return (
{children}
<div className="scrollbar">
<div
className="scroll-thumb"
style={{
height: thumbHeight,
transform: `translateY(${thumbTop}px)`
}}
/>
</div>
</div>
); } 4. Styling the Scrollbar CustomScrollbar.css .scroll-container { position: relative; height: 300px; }
.scroll-content { height: 100%; overflow-y: scroll; padding-right: 10px; }
/* hide native scrollbar */ .scroll-content::-webkit-scrollbar { display: none; }
.scrollbar { position: absolute; right: 2px; top: 0; width: 8px; height: 100%; background: transparent; }
.scroll-thumb { width: 100%; background: #888; border-radius: 4px; position: absolute; cursor: pointer; } 5. Using the Custom Scrollbar import CustomScrollbar from "./CustomScrollbar";
function App() { return ( {Array.from({ length: 50 }).map((_, i) => (
Item {i}
))} ); }
export default App;
Now your React app uses a custom scrollbar instead of the native one.
- Adding Drag Support (Advanced)
To make the scrollbar thumb draggable, we handle mouse events.
Example logic:
const handleMouseDown = (e) => { const startY = e.clientY;
const onMouseMove = (moveEvent) => { const delta = moveEvent.clientY - startY; contentRef.current.scrollTop += delta * 2; };
const onMouseUp = () => { document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mouseup", onMouseUp); };
document.addEventListener("mousemove", onMouseMove); document.addEventListener("mouseup", onMouseUp); };
Attach it to the thumb:
7. Libraries That Provide Custom Scrollbars
If you prefer a production-ready solution, consider these libraries:
react-custom-scrollbars
simplebar-react
react-scrollbars-custom
These libraries handle:
touch support
accessibility
performance optimization
cross-browser compatibility
Conclusion
Custom scrollbars can significantly improve the visual polish and user experience of your React applications.
You have three main options:
Method Difficulty Flexibility CSS Scrollbar Styling Easy Low Custom React Component Medium High Library Solution Easy Very High
For small projects, CSS styling is enough. For design-heavy applications like dashboards or design systems, building a custom React scrollbar provides much greater control.