Scroll area

Gives long content its own scrolling box.

Examples

Goals in a panel

A strip of goals

Orientation

  • verticaldefault

  • horizontal

  • both

States

  • rest

  • hovering

  • focus-visible

  • nothing to scroll

Usage

When to use it
Use
A list inside a panel or popover with a fixed height, such as a merchant picker.
Use
A code block or wide strip of chips that scrolls sideways.
Use
A panel that must cap its height.
Not for
The page itself. Let the browser scroll it.
Not for
A long list inside a Select, which caps and scrolls its own popup. Use Select.
Not for
A table wider than its column; Table scrolls in its own wrapper. Use Table.

Rules

7 rules
Must
Give a vertical scroll area a height or max height. Because without one the area grows with its rows and never scrolls.
Should
Let a row be cut by the edge; the thumb is hidden at rest, so a cut item says there is more.
Should
Pass aria-label such as "Merchants"; the viewport is a focus stop and needs a name.
Never
Hide the scrollbar with CSS; use ScrollArea, which keeps native scrolling and a thumb. Because a hidden bar never shows, even on hover, so a mouse user cannot tell the list scrolls.
Should
Prefer vertical; use orientation="both" only for tables and frames.
Must
Keep the viewport focusable so arrow keys scroll it; never tabIndex -1. Because a keyboard user cannot reach an unfocusable region, so rows below the fold are lost.
Should
Set overscroll-contain in a popover or dialog so scrolling does not chain to the page.

Accessibility

5 checks
The viewport is a Tab stop that scrolls with arrow keys, Page and Home or End.
Focus shows a 2px olive ring inside the edge.
Name the region with aria-label.
Native scrolling and momentum are kept; the 10px thumb is not for finger dragging.
The thumb is a background fill and may vanish in forced colors; scrolling still works.

Edge cases

6 edge cases
Right to left
The vertical bar moves to the left edge, following the writing direction. The specimen keeps the thumb shown.
Long unbroken string
It overflows sideways and scrolls only if orientation includes horizontal.
Short content
No thumb; the area keeps the height you gave it.
Thousands of items
Use a virtual list; 500 nodes scroll natively.
More loads on scroll
Add your own sentinel; the area has no loading part.
Reduced motion
The thumb appears and goes at once.

API

2 props
orientation
'vertical' | 'horizontal' | 'both' default 'vertical'
className
string

Tokens

4 tokens
--line-strong
#cfcdc6
--control
#85827a
--scrollbar-thumb
var(--line-strong)
--dur-fast
140ms

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.