---
id: "packages/active-ui/scroll-area"
title: "ScrollArea"
description: "Content that scrolls inside a box of fixed size, with the package's scrollbar in every browser."
url: "/packages/active-ui/scroll-area"
locale: "en"
revision: "a2f00c7b1fc43a75"
---

# ScrollArea

A scroll area lets content scroll inside a box of fixed size, with a slim scrollbar that looks the
same in every browser and theme. Use it for a panel inside a page: a list in a popover, a log, a
row of tiles. The page itself scrolls natively. It is built on Base UI's scroll area. For the long
option lists of a picker, the composed [`ListScrollArea`](/packages/active-ui/list-scroll-area) adds the details of a listbox.

**Example: A long list, and a row that scrolls sideways**

Client: Runs entirely in your browser. Source: `examples/ui/scroll-area.tsx`.

```tsx
// apps/docs/examples/ui/scroll-area.tsx
'use client';

import {
  ScrollArea,
  ScrollBar,
} from '@workspace/active-ui/components/primitives/scroll-area';
import {Separator} from '@workspace/active-ui/components/primitives/separator';

const EVENTS = Array.from(
  {length: 40},
  (_, index) => `Statement ${String(index + 1).padStart(2, '0')} sent`,
);
const YEARS = Array.from({length: 12}, (_, index) => 2015 + index);

/**
 * Content that scrolls inside a fixed box, with the package's scrollbar: a
 * long list vertically, and a row of tiles sideways with a horizontal
 * scrollbar added.
 */
export default function ScrollAreaExample() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-6">
      <ScrollArea className="h-56 rounded-md border">
        <div className="p-4">
          <h4 className="mb-3 text-sm font-semibold">Activity</h4>
          {EVENTS.map((event, index) => (
            <div key={event}>
              {index > 0 ? <Separator className="my-2" /> : null}
              <p className="text-sm">{event}</p>
            </div>
          ))}
        </div>
      </ScrollArea>
      <ScrollArea className="w-full rounded-md border whitespace-nowrap">
        <div className="flex w-max gap-3 p-4">
          {YEARS.map((year) => (
            <div
              key={year}
              className="bg-muted flex size-20 shrink-0 items-center justify-center rounded-md text-sm font-medium"
            >
              {year}
            </div>
          ))}
        </div>
        <ScrollBar orientation="horizontal" />
      </ScrollArea>
    </div>
  );
}
```

## Usage

```tsx
import {ScrollArea} from '@workspace/active-ui/components/primitives/scroll-area';

<ScrollArea className="h-56 rounded-md border">{longContent}</ScrollArea>;
```

## Anatomy

- `ScrollArea`: the box and its viewport, with a vertical scrollbar and the corner. Give it a
  height (or a width) for content to scroll in.
- `ScrollBar`: a scrollbar; `orientation="horizontal"` adds the sideways one, as in the example.

## What your application provides

- The size of the box.
- For a horizontal row: content wider than the box (`w-max`, `whitespace-nowrap`).

## Accessibility and keyboard

- The viewport takes focus when it can scroll, so the arrow keys, `Page Up` and `Page Down`
  scroll it; it shows the focus ring.
- The scrollbars are for the pointer; the wheel, touch and the keyboard scroll the content too.

## API

**ScrollArea**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `overflowEdgeThreshold` | `number \| Partial<{ xStart: number; xEnd: number; yStart: number; yEnd: number; }>` | no | The threshold in pixels that must be passed before the overflow edge attributes are applied. Accepts a single number for all edges or an object to configure them individually. |
| `render` | `ComponentRenderFn<HTMLProps, ScrollAreaRootState> \| ReactElement<unknown, string \| JSXElementConstructor<any>>` | no | Allows you to replace the component's HTML element with a different tag, or compose it with another component.  Accepts a `ReactElement` or a function that returns the element to render. |

**ScrollBar**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `keepMounted` | `boolean` | no | Whether to keep the HTML element in the DOM when the viewport isn't scrollable. |
| `orientation` | `"horizontal" \| "vertical"` | no | Whether the scrollbar controls vertical or horizontal scroll. |
| `render` | `ComponentRenderFn<HTMLProps, ScrollAreaScrollbarState> \| ReactElement<unknown, string \| JSXElementConstructor<any>>` | no | Allows you to replace the component's HTML element with a different tag, or compose it with another component.  Accepts a `ReactElement` or a function that returns the element to render. |

> [!NOTE]
> **Based on shadcn/ui**
>
> This page adapts the Scroll Area documentation of shadcn/ui (MIT licence) to
> this package; see [Third-party notices](/third-party-notices).
