Styled scroll container with overlay scrollbars for vertical, horizontal, or both axes.
Description
ScrollArea is a styled wrapper around Radix's ScrollArea primitive. It renders a viewport plus overlay scrollbars that match the design system, so a scrolling region inside a card, panel, or popover doesn't fall back to the browser's native scrollbar.
Reach for it when content needs to scroll inside a fixed-size surface: long tag lists in a sidebar, image rows in a gallery card, release matrices, dropdown menus that overflow, code blocks, anywhere the native scrollbar would clash with the surrounding chrome. From the consumer's perspective it's a single element. The viewport, track, and thumb are all rendered for you.
Don't use ScrollArea for full-page scrolling. The browser handles that more efficiently and accessibly than any JS-driven solution. Skip it for short content that already fits its container (a scrollbar that never appears is just dead weight). For tabular data prefer the table's own overflow behavior; ScrollArea is for free-form content.
Installation
Usage
Examples
Vertical
The default orientation. Set a fixed height (and width if needed) on the root via className; the viewport scrolls vertically as soon as its content exceeds that height.
Horizontal
Pass orientation="horizontal" for a single-axis horizontal scroller. The track flips to the bottom edge and the content row scrolls left/right.
Both Axes
orientation="both" enables both scrollbars at once. Useful for wide grids, large diagrams, or tables that exceed the surface in both dimensions.
Fade
Enable fade to render a gradient overlay at the scroll-end of each enabled axis. The overlay fades out once the viewport reaches the end of the content, signalling "there's more below / to the right" without adding a hard divider.
Sizes
size controls scrollbar thickness. sm is unobtrusive for dense surfaces, md (default) is the everyday choice, lg is meant for touch targets or content-heavy panels where the bar doubles as a hint.
Appearance
appearance swaps the track styling. filled (default) adds a bg-weak track so the scrollbar reads as a distinct surface; ghost removes the track entirely and leaves only the thumb, useful inside already-tinted surfaces.
Accessibility
The viewport is keyboard-scrollable once focused. Radix exposes the viewport with tabIndex={0} so it lands in the tab order, which means screen-reader and keyboard-only users can scroll without a pointer.
ARIA notes:
- The scrollbars and thumb are decorative and marked
aria-hidden. They expose no role, since pointer drag is the only thing they're meant for. - Give the
ScrollAreaan accessible name (aria-labeloraria-labelledby) when it's the primary content of a section so the focus stop announces meaningfully. - For long content regions, consider rendering a heading inside the viewport (
<h2>,<h3>, etc.) so the structure is reachable by landmark navigation. - Built on Radix Scroll Area; see Radix's docs for the underlying primitive's behavior and props.
Styling
Tailwind override: pass className to set sizing and surface styles on the root. Width and height live on the root, not the viewport.
Data slots and attributes: the component sets these for CSS targeting:
data-slot="scroll-area"on the root element.data-slot="scroll-area-viewport"on the inner viewport that wrapschildren.data-slot="scroll-area-scrollbar"on each scrollbar track, withdata-orientation="vertical | horizontal".data-slot="scroll-area-thumb"on the draggable thumb.data-slot="scroll-area-fade"on each fade overlay, withdata-orientationanddata-state="visible | hidden".
Target a specific slot in CSS:
Related Components
- Separator: divider lines between rows inside a scrolled list.
- Table: use the table's own overflow for tabular data;
ScrollAreais for free-form content. - Tooltip / Popover: when the overflow is a small floating panel, the popover primitive already handles its own scroll surface.
API Reference
ScrollArea
Wraps Radix's ScrollArea.Root and renders a viewport plus styled scrollbars. Accepts every prop the Radix root accepts (type, scrollHideDelay, dir, etc.). ScrollBar is exported separately for advanced layouts that need to render a scrollbar in a custom position.