Custom Scrollbar
A customizable animated scrollbar, with the thumb tracking the scroll on a spring, draggable, and click-the-track to jump.
A custom scrollbar driven by a motion/react spring: the native scrollbar is hidden and replaced with a thumb that can be dragged, jumped to by clicking the track, and that supports gradients and autoHide, with a touch of momentum feedback while scrolling.
npx shadcn@latest add https://webberui.com/r/custom-scrollbar.jsonPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<CustomScrollbar />
Installation
npx shadcn@latest add https://webberui.com/r/custom-scrollbar.jsonOr, once registries are configured in components.json, install it as @webberui/custom-scrollbar.
Usage
import { CustomScrollbar } from "@/components/ui/custom-scrollbar";
<CustomScrollbar maxHeight={280} width={9} autoHide>
<div className="p-5">{/* your long content */}</div>
</CustomScrollbar>maxHeight decides the height of the content area, and anything beyond it scrolls. The thumb height is calculated automatically from the content ratio. Pass a CSS gradient string to thumbColor to build a colored scrollbar.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | — | The content to wrap and make scrollable |
maxHeight | number | string | 300 | Maximum height of the content area; anything beyond it scrolls |
width | number | 8 | Scrollbar width (px) |
thumbColor | string | indigo-violet gradient | Thumb color; a CSS gradient string is accepted |
thumbHoverColor | string | — | Thumb color while the pointer is over the scrollbar |
trackColor | string | rgba(120,120,140,0.14) | Track background color |
showTrack | boolean | true | Whether to show the track background color |
autoHide | boolean | false | Fades out while idle, and fades in on scroll, hover, or drag |
Accessibility
- When the user has "reduce motion" enabled at the system level, the thumb tracks the scroll instantly with no spring momentum applied
- Native scrolling behavior is fully preserved (wheel, touch, keyboard); the custom thumb layer carries
aria-hiddenand is visual feedback only - Never use viewport height units such as
100vh; give it an explicit bound throughmaxHeightinstead