ScrollArea

A bounded, hand-drawn scroll viewport with a sketchy border and a token-themed scrollbar.

Overview

ScrollArea is a bounded scroll viewport: it draws a hand-drawn border around a scrollable region whose native scrollbar is themed to match the design system. Use it to cap the height (or width) of overflowing content — a long list, a code block, a panel of options — while keeping the sketchy look consistent.

Anatomy

A sketchy border (@ghds/sketch-core) around an inner viewport. The viewport uses the standard scrollbar-color / scrollbar-width CSS properties, so the thumb and track pick up comp.scrollArea.* tokens without a custom scrollbar overlay (Firefox and Chromium 121+). Constrain the region by passing maxHeight (or maxWidth) via style.

Variants & States

No interactive states — the only axis is orientation, which chooses the scroll axis.

State Status Notes
Hover Not implemented
Focus Not implemented The scroll region is keyboard-scrollable when focused, but paints no focus style itself.
Disabled Not implemented
Loading Not implemented
Error Not implemented

The orientation prop is 'vertical' (default), 'horizontal', or 'both'.

Usage

Do

  • Constrain the box with maxHeight (or maxWidth) via style — that bound is what makes content scroll.
  • Match orientation to the axis your content actually overflows on.
  • Keep the scrolled content simple; the viewport is a plain overflow container.

Don't

  • Don't nest scroll areas on the same axis; it traps the user in dueling scrollbars.
  • Don't rely on the themed scrollbar for browsers older than Chromium 121 — they fall back to the native scrollbar.

Accessibility

Content

N/A — ScrollArea has no fixed content model. It bounds whatever children you place inside and lets them overflow along the chosen axis.

Props API

React@ghds/react

PropTypeDefaultDescription
orientation'vertical' | 'horizontal' | 'both''vertical'Which axis (or axes) the region scrolls.
...restHTMLAttributes<HTMLDivElement>Native <div> attributes pass through; use style to set maxHeight / maxWidth.

Web Components@ghds/web-components

PropTypeDefaultDescription
orientation'vertical' | 'horizontal' | 'both''vertical'Reflected attribute; which axis (or axes) the region scrolls.
(default slot)slotThe scrollable content. Set max-height (or max-width) on the host.

React Native@ghds/react-native

PropTypeDefaultDescription
orientation'vertical' | 'horizontal' | 'both''vertical'Which axis (or axes) the region scrolls (wraps native ScrollView).
childrenReactNodeScrollable content.
styleStyleProp<ViewStyle>Merged onto the bordered box; constrain height/width here (e.g. maxHeight).
accessibilityLabelstringAccessible label for the scroll region.
testIDstringTest handle for queries.

Code examples

// React — @ghds/react
import { ScrollArea } from '@ghds/react/scroll-area';

<ScrollArea orientation="vertical" style={{ maxHeight: 200, maxWidth: 360 }}>
  {/* long content */}
</ScrollArea>;
<!-- Web Components — @ghds/web-components -->
<script type="module">
  import '@ghds/web-components/scroll-area';
</script>
<gh-scroll-area orientation="vertical" style="max-height: 200px; max-width: 360px;">
  <!-- long content -->
</gh-scroll-area>
// React Native — @ghds/react-native
import { ScrollArea } from '@ghds/react-native/scroll-area';

<ScrollArea orientation="vertical" style={{ maxHeight: 200 }}>
  {/* long content */}
</ScrollArea>;

Live Demo

React and Web Components render live below, driven by the same tokens — scroll either to reveal the token-themed scrollbar, and toggle dark mode in the header to see both respond identically. React Native can’t run in a browser without additional react-native-web wiring (not set up in this site), so its usage is shown as a code sample instead. (On React Native the native scrollbar can’t be themed, so the platform scroll indicators are kept as-is.)

React @ghds/react

Web Components @ghds/web-components

1. The quick brown fox jumps over the lazy dog, again and again until the box overflows and the themed scrollbar appears.

2. The quick brown fox jumps over the lazy dog, again and again until the box overflows and the themed scrollbar appears.

3. The quick brown fox jumps over the lazy dog, again and again until the box overflows and the themed scrollbar appears.

4. The quick brown fox jumps over the lazy dog, again and again until the box overflows and the themed scrollbar appears.

5. The quick brown fox jumps over the lazy dog, again and again until the box overflows and the themed scrollbar appears.

6. The quick brown fox jumps over the lazy dog, again and again until the box overflows and the themed scrollbar appears.

7. The quick brown fox jumps over the lazy dog, again and again until the box overflows and the themed scrollbar appears.

8. The quick brown fox jumps over the lazy dog, again and again until the box overflows and the themed scrollbar appears.