Skip to content
garn

Scroll Area

A height-constrained region with a styled, cross-browser scrollbar.

Stablev0.4.2added in v0.1.0@garn/ui/scroll-area
On this page

Default

A fixed-height vertical list with a styled scrollbar.

Installation

garn is copy-in — the garn CLI writes this component's source into your project, so you own and can edit it. It resolves any base files and installs the npm dependencies below for you.

terminal
npx garn-ui add scroll-area
First time? Set up garn in your project
Registry
scroll-area
Deps
@radix-ui/react-scroll-area
Registry deps
utils

Import

import { ScrollArea, ScrollBar } from "@garn/ui/scroll-area";

Anatomy

The parts this component is built from — compose them to assemble it.

ScrollAreaRequired[data-slot="scroll-area"]

Root + Viewport; renders a vertical ScrollBar and a Corner. Children render inside the scrolling viewport.

ScrollBar[data-slot="scroll-bar"]

The scrollbar track + thumb. orientation vertical (default) | horizontal — compose a horizontal bar for horizontal overflow.

Props

The component's public props and their types.

No component-specific props — this is a thin wrapper over its native element.

Styling

Target these data-slots and states, and remap these tokens, to restyle without forking the component.

[data-slot="scroll-area"]

States

SelectorState
[data-state=visible]scrollbar-visible
[data-state=hidden]scrollbar-hidden

When to use

Give a height-constrained region its own styled scrollbar — a sidebar, a long list, a code block, a chat log.

Reach for something else when

  • The whole page (let the document scroll natively)
  • content that must never be clipped (let it flow)
  • a few items that already fit.

Overview

ScrollArea gives a height-constrained region its own consistently-styled scrollbar — a sidebar, a long list, a code block, a chat log — instead of the OS default that varies by platform. ScrollArea is the root + viewport (children scroll inside), and ScrollBar is the track/thumb (vertical by default; add a horizontal one for horizontal overflow). Use it for a bounded scrolling pane; for whole-page scrolling, let the document scroll natively.

Guidelines

Use it for bounded regions, not the whole page. It shines on a fixed-height panel that needs to scroll independently with a tidy scrollbar; hijacking the document scroll is the wrong call. Give the region a real height constraint so there's something to scroll.

Never trap content behind a scrollbar users can't see. Ensure the area is keyboard-scrollable and that important content isn't hidden with no scroll cue; on touch, native momentum should still work. Add a horizontal ScrollBar only when content truly overflows sideways.

Keep the scrollbar legible and unobtrusive. Style it to read clearly against the surface without dominating it, and don't shrink the thumb so far it's hard to grab. Respect reduced-motion for any scroll animations.

Best practices

Do
  • Set an explicit height / max-height on the ScrollArea (or its container) so there's something to scroll.
  • Keep important content reachable — don't hide the only copy of critical info behind a scroll region.
  • Use the Root type (auto / always / scroll / hover) to decide when the bar shows.
Don't
  • Don't wrap the entire page — use native document scroll.
  • Don't set a height that clips content without leaving a scroll affordance.
  • Don't rely on type="hover" as the only hint that more content exists.

Content guidelines

  • The scroll region has no text of its own — give it an accessible label when it's a distinct, navigable area.

Troubleshooting

No scrollbar appears and content is cut off.

Cause. The ScrollArea (or its parent) has no bounded height, so there's no overflow to scroll.

Fix. Give the ScrollArea an explicit height / max-height.

Horizontal content doesn't get a scrollbar.

Cause. ScrollArea renders a vertical ScrollBar by default.

Fix. Compose a <ScrollBar orientation="horizontal" /> (and let the content exceed the viewport width).

Accessibility

AA1.4.10ReflowA2.1.1Keyboard
  • Native scrolling is preserved — wheel, touch, and keyboard (when the viewport has focus) all still work; the styled bar is an overlay.
  • Set the Root `type` to control when the scrollbar appears; `auto`/`always` keep it discoverable for everyone.