Scroll Area

Styled custom scroll container.

Usage

Compose Root > Viewport plus one Scrollbar per axis, each holding a Thumb. Put the height or width constraint on Root — the Viewport fills it and does the actual scrolling.

Row 0

Row 1

Row 2

Row 3

Row 4

Row 5

Row 6

Row 7

Row 8

Row 9

Row 10

Row 11

Row 12

Row 13

Row 14

Row 15

Row 16

Row 17

Row 18

Row 19

Row 20

Row 21

Row 22

Row 23

When the scrollbar shows

type controls visibility: hover (the default) shows it on pointer hover, scroll only while scrolling, auto follows the platform, and always keeps it visible.

Worth knowing: under hover the scrollbar is not merely transparent — it is not in the DOM at all until the pointer enters. That is Bits behaviour, and it is why the demo above uses always.

The cost of hiding it

A hidden scrollbar removes the only visual cue that more content exists.

That is the real trade-off of a styled scroll area, and it is easy to miss on a trackpad where you scroll by reflex. Prefer always whenever the overflow is not obvious from the content itself — a clipped row of text hints at more, a neatly clipped card does not.

The good news is that only the chrome is restyled. Bits keeps the Viewport a real scroll container, so wheel, touch and keyboard scrolling all keep working natively — this never traps a keyboard user, and it does not virtualise your content.

Props

ScrollArea.Root

PropTypeDefault
type When the scrollbars are visible. `hover` shows them on pointer hover, `always` keeps them visible, `auto` follows the platform, `scroll` shows them only while scrolling.'hover' | 'scroll' | 'auto' | 'always''hover'
class Extra classes merged onto the root.string—
child bits-ui Snippet<[{ props: Record<string, unknown>; }]> | undefined—
children bits-ui Snippet<[]> | undefined—
dir bits-ui The reading direction of the application.Direction | undefined—
id bits-ui string | undefined—
ref bits-ui HTMLElement | null | undefined—
scrollHideDelay bits-ui The amount of time in milliseconds to delay before hiding the scrollbars after leaving the scroll area or stopping scrolling.number | undefined600

ScrollArea.Scrollbar — orientation is required by Bits; render one per axis you want styled.

PropTypeDefault
class Extra classes merged onto the scrollbar track.string—
child bits-ui Snippet<[{ props: Record<string, unknown>; }]> | undefined—
children bits-ui Snippet<[]> | undefined—
forceMount bits-ui Whether to forcefully mount the component. Useful when working with external animation/transition libraries.boolean | undefined—
id bits-ui string | undefined—
orientation required bits-ui Orientation—
ref bits-ui HTMLElement | null | undefined—

Viewport and Thumb each take class plus their native attributes.