Skip to content

ScrollArea

ScrollArea is a scrolling box with thin overlay scrollbars in the style of macOS: a rounded thumb that fades in while you scroll or hover, thickens when you point at it (there is no visible track), and fades out about a second after scrolling stops. It looks the same in every theme and on every platform. Scrolling itself stays native, so the wheel, trackpad, touch and keyboard work as usual; the thumb can also be dragged, and pressing the empty space beside it pages.

Demos

Basic

Give the scroll area a height (or a max-height). Put padding on the content with contentClassName or contentStyle, not on the scroll area itself, so the scrollbars stay at the edges.

Horizontal

xScrollable lets wide content scroll sideways and adds a horizontal scrollbar. When both directions overflow, each scrollbar stops short of the corner.

Trigger

By default the scrollbars show while the pointer is over the area and while it scrolls. trigger="none" keeps them visible.

Size

size sets the thumb thickness: small is 5px and medium 7px. Both grow by 3px while the scrollbar is pointed at or the thumb is dragged.

Scrolling from code

The scroll area is the scrolling element, so a ref gets the native scrollTo and scrollBy, and onScroll receives its scroll events.

Textarea

A <textarea> scrolls itself, so ScrollAreaTextarea wraps a native textarea and lays the same scrollbar over it. Frame the wrapper (wrapperClassName: border, background, focus ring) and pad the textarea (className); the scrollbar follows typing, pasting and a controlled value. Drag the bottom corner to make the textarea taller; the scrollbar stops above the grip so it stays reachable.

Props

NameTypeDefaultDescriptionVersion
triggerhover | nonehoverhover shows the scrollbars while the pointer is over the area; none always shows them. They always show while scrolling or dragging.Unreleased
xScrollablebooleanfalseAlso scroll horizontally, with a horizontal scrollbar. Otherwise wide content is cut off.Unreleased
sizesmall | mediummediumThumb thickness: 5px or 7px, 3px more on hover.Unreleased
contentClassNamestringundefinedClass of the element that wraps children.Unreleased
contentStyleCSSPropertiesundefinedStyle of the element that wraps children.Unreleased
onScroll(event: UIEvent<HTMLDivElement>) => voidundefinedCalled on every scroll of the area.Unreleased
childrenReactNodeundefinedThe scrolling content.Unreleased

ScrollArea also accepts native div attributes and a ref to the scrolling element; use the element’s own scrollTo and scrollBy instead of a component method. When there is something to scroll, the area is focusable (tabIndex={0}) so keyboard users can scroll it with the arrow keys; give it an aria-label that says what it contains. The custom scrollbars are hidden from assistive technology, which uses the native scrolling instead.

ScrollAreaTextarea Props

NameTypeDefaultDescriptionVersion
triggerhover | nonehoverAs on ScrollArea.Unreleased
sizesmall | mediummediumAs on ScrollArea.Unreleased
wrapperClassNamestringundefinedClass of the wrapper that holds the textarea and its scrollbar. Put the border and background here.Unreleased
wrapperStyleCSSPropertiesundefinedStyle of the wrapper.Unreleased

Every other prop, including ref, className, style, value and onScroll, goes to the native textarea.