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

ScrollArea.Scrollbarorientation is required by Bits; render one per axis you want styled.

PropTypeDefault
class Extra classes merged onto the scrollbar track.string

Viewport and Thumb each take class plus their native attributes.