Skip to content
RefineUI

Scroll Area

Custom styled scrollbar container.

  • Accordion
  • Alert
  • Avatar
  • Badge
  • Bubble
  • Button
  • Calendar
  • Card
  • Carousel
  • Checkbox
  • Dialog
  • Divider
  • Drawer
  • Dropdown
  • Field
  • Input
  • Label
  • Link
  • Menu
  • Pagination
  • PopOver
  • Progress
  • ProgressStepper
  • Radio
  • Resizable
  • ScrollArea
  • Select
  • Skeleton
  • Slider
  • Spinner
  • Stepper
  • Switch
  • SegmentedControl
  • Tabs
  • Tag
  • Textarea
  • Toast
  • Tooltip

Overview

Machine-readable contract from Component Spec.

component: scroll-areaexport: ScrollAreaversion: 1attributes: data-refineui=scroll-area

Anatomy

Partdata-refineui
rootscroll-area
scrollbarscroll-area-scrollbar
thumbscroll-area-thumb
trackscroll-area-track
viewportscroll-area-viewport

Variants

AxisValues
typehover, always

States

ScopeCategoryValues
componentcomponentdata-state: visible, hidden
componentenvironmentforced-colors, dir
scroll-area-scrollbarcomponentdata-state: visible, hidden

Layout

PropertyValue
directionlogical
rtltrue
npm install @refineui/react @refineui/tokens
import { ScrollArea, ScrollAreaViewport, ScrollAreaScrollbar, ScrollAreaThumb } from "@refineui/react";
<ScrollArea className="h-80">
<ScrollAreaViewport>
{/* Long content */}
</ScrollAreaViewport>
<ScrollAreaScrollbar orientation="vertical">
<ScrollAreaThumb />
</ScrollAreaScrollbar>
</ScrollArea>
<ScrollArea type="always">
<ScrollAreaViewport>
{/* Custom viewport */}
</ScrollAreaViewport>
<ScrollAreaScrollbar orientation="vertical">
<ScrollAreaThumb />
</ScrollAreaScrollbar>
<ScrollAreaScrollbar orientation="horizontal">
<ScrollAreaThumb />
</ScrollAreaScrollbar>
</ScrollArea>
<ScrollArea className="h-80">
<ScrollAreaViewport>
{rows.map((row) => (
<div key={row.id} data-scroll-edge-item>{row.label}</div>
))}
</ScrollAreaViewport>
<ScrollAreaScrollbar orientation="vertical">
<ScrollAreaThumb />
</ScrollAreaScrollbar>
</ScrollArea>

The edge effect is always on. Rows marked data-scroll-edge-item soften like a picker wheel’s edge: rows blur progressively across the outer quarter of the scrollport on each side (scrollEdge blur), while size and opacity never change. It only applies toward an edge that actually hides content — a list that does not scroll, or the edge you are parked at, stays untouched, and the blur fades in as you scroll away. Unmarked content is never affected. It is scroll-driven (animation-timeline: view()), so it follows the scroll exactly; where that is unsupported, or with prefers-reduced-motion, rows simply stay as they are. Elements between the viewport and the rows must not be scroll containers — use overflow: clip instead of overflow: hidden. Command, Select, Dropdown, and Sidebar mark their rows.

PropDefaultTypeDescription
type"hover""hover" | "always"When the custom scrollbar is visible.

Viewport container (scrollable area).

An axis becomes scrollable only when its ScrollAreaScrollbar is declared, so a horizontal-only area lets vertical wheel gestures scroll the page instead of swallowing them. The viewport is a tab stop only while its content actually overflows.

PropDefaultTypeDescription
orientation"vertical""vertical" | "horizontal"Scrollbar direction.

Scrollbar thumb (draggable handle).