Embossed UI

Search documentation

Search for a page or component.

Scroll Area

Augments native scroll functionality for custom, cross-browser styling.

import * as React from "react"

import { ScrollArea } from "@/components/ui/scroll-area"
import { Separator } from "@/components/ui/separator"

const tags = Array.from({ length: 50 }).map(
  (_, i, a) => `v1.2.0-beta.${a.length - i}`
)

export function ScrollAreaDemo() {
  return (
    <ScrollArea className="h-72 w-48 rounded-lg border">
      <div className="p-4">
        <h4 className="mb-4 text-sm leading-none font-medium">Tags</h4>
        {tags.map((tag) => (
          <React.Fragment key={tag}>
            <div className="text-sm tabular-nums">{tag}</div>
            <Separator className="my-2" />
          </React.Fragment>
        ))}
      </div>
    </ScrollArea>
  )
}

Installation

pnpm dlx shadcn@latest add https://ui.ikramhasan.com/r/scroll-area.json

Usage

import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"
<ScrollArea className="h-[200px] w-[350px] rounded-lg border p-4">
  Your scrollable content here.
</ScrollArea>

The scrollbar is a 6px thumb in a 10px track, in muted-foreground at 50% like the menus' scrollbars. It widens to 8px and darkens while you hover or drag it. The track sits inside the border, and its round ends clear corners up to rounded-lg. For a rounder container, inset the bar with className (e.g. data-vertical:py-2).

Composition

Use the following composition to build a ScrollArea:

ScrollArea
└── ScrollBar

Examples

Horizontal

Use ScrollBar with orientation="horizontal" for horizontal scrolling.

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

const swatches = [
  { name: "Dawn", from: "oklch(0.86 0.09 60)", to: "oklch(0.7 0.15 20)" },
  { name: "Lagoon", from: "oklch(0.88 0.08 190)", to: "oklch(0.6 0.12 230)" },
  { name: "Moss", from: "oklch(0.88 0.1 130)", to: "oklch(0.55 0.11 150)" },
  { name: "Dusk", from: "oklch(0.8 0.1 300)", to: "oklch(0.45 0.15 275)" },
  { name: "Ember", from: "oklch(0.9 0.12 90)", to: "oklch(0.62 0.19 40)" },
  { name: "Slate", from: "oklch(0.9 0.01 250)", to: "oklch(0.5 0.03 250)" },
]

export function ScrollAreaHorizontalDemo() {
  return (
    <ScrollArea className="w-96 rounded-lg border whitespace-nowrap">
      <div className="flex w-max gap-4 p-4">
        {swatches.map((swatch) => (
          <figure key={swatch.name} className="shrink-0">
            <div
              className="aspect-[3/4] w-32 rounded-md outline outline-1 -outline-offset-1 outline-black/10 dark:outline-white/10"
              style={{
                backgroundImage: `linear-gradient(to bottom, ${swatch.from}, ${swatch.to})`,
              }}
            />
            <figcaption className="pt-2 text-xs text-muted-foreground">
              Gradient{" "}
              <span className="font-medium text-foreground">{swatch.name}</span>
            </figcaption>
          </figure>
        ))}
      </div>
      <ScrollBar orientation="horizontal" />
    </ScrollArea>
  )
}

Both directions

ScrollArea always renders a vertical bar. Add a horizontal ScrollBar for content that overflows both ways.

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

const log = Array.from({ length: 40 }).map((_, i) => {
  const second = String(i).padStart(2, "0")
  const status = i % 7 === 3 ? "WARN" : "INFO"
  return `12:04:${second} ${status} sync worker-${(i % 3) + 1} processed batch ${1200 + i * 17} (orders, customers, products) in ${80 + ((i * 37) % 140)}ms`
})

export function ScrollAreaBoth() {
  return (
    <ScrollArea className="h-64 w-full max-w-md rounded-lg border">
      <pre className="w-max p-4 font-mono text-xs leading-5 text-muted-foreground">
        {log.join("\n")}
      </pre>
      <ScrollBar orientation="horizontal" />
    </ScrollArea>
  )
}

API Reference

ScrollArea wraps Base UI's ScrollArea.Root (data-slot="scroll-area"), with a Viewport (scroll-area-viewport), a vertical ScrollBar and a Corner inside it. ScrollBar wraps ScrollArea.Scrollbar (scroll-area-scrollbar) and its Thumb (scroll-area-thumb) and takes orientation ("vertical" by default, or "horizontal").

See the Base UI Scroll Area documentation for every prop.