WebberUI

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.

Loading preview…
npx shadcn@latest add https://webberui.com/r/custom-scrollbar.json

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

300
8
<CustomScrollbar />

Installation

npx shadcn@latest add https://webberui.com/r/custom-scrollbar.json

Or, 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

PropTypeDefaultDescription
childrenReact.ReactNodeThe content to wrap and make scrollable
maxHeightnumber | string300Maximum height of the content area; anything beyond it scrolls
widthnumber8Scrollbar width (px)
thumbColorstringindigo-violet gradientThumb color; a CSS gradient string is accepted
thumbHoverColorstringThumb color while the pointer is over the scrollbar
trackColorstringrgba(120,120,140,0.14)Track background color
showTrackbooleantrueWhether to show the track background color
autoHidebooleanfalseFades 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-hidden and is visual feedback only
  • Never use viewport height units such as 100vh; give it an explicit bound through maxHeight instead

On this page