Scroll Area

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

Vertical
Horizontal

Installation

Install the dependencies

pnpm add cn class-variance-authority github:sveltery/base

Copy the component

Copy the following files into src/lib/components/ui/scroll-area.

src/lib/components/ui/scroll-area/ScrollArea.svelte
<script lang="ts">
  import { ScrollArea as Primitive, type ScrollAreaRootProps } from '@sveltery/base/scroll-area';
  import { cn } from 'cn';
  import ScrollBar from './ScrollBar.svelte';
  let { children, class: classProp, ...props }: ScrollAreaRootProps = $props();
</script>
<Primitive.Root data-slot="scroll-area" {...props} class={cn('relative', classProp)}>
  <Primitive.Viewport
    data-slot="scroll-area-viewport"
    class="size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1"
  >
    {@render children?.()}
  </Primitive.Viewport>
  <ScrollBar />
  <Primitive.Corner />
</Primitive.Root>
src/lib/components/ui/scroll-area/ScrollBar.svelte
<script lang="ts">
  import { ScrollArea as Primitive, type ScrollAreaScrollbarProps } from '@sveltery/base/scroll-area';
  import { cn } from 'cn';
  let { class: classProp, orientation = 'vertical', ...props }: Omit<ScrollAreaScrollbarProps, 'children'> = $props();
</script>
<Primitive.Scrollbar
  data-slot="scroll-area-scrollbar"
  data-orientation={orientation}
  {orientation}
  {...props}
  class={cn('data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent flex touch-none p-px transition-colors select-none', classProp)}
>
  <Primitive.Thumb data-slot="scroll-area-thumb" class="rounded-full relative flex-1 bg-border" />
</Primitive.Scrollbar>
src/lib/components/ui/scroll-area/index.ts
export { default as ScrollArea } from './ScrollArea.svelte';
export { default as ScrollBar } from './ScrollBar.svelte';
export type { ScrollAreaRootProps as ScrollAreaProps, ScrollAreaScrollbarProps as ScrollBarProps } from '@sveltery/base/scroll-area';

Update the import paths

Change the imports to match your project setup.

Usage

<script lang="ts">
  import { ScrollArea, ScrollBar } from '$lib/components/ui/scroll-area';
</script>
<ScrollArea class="h-72 w-48 rounded-md border">
  <div class="p-4">Long content</div>
  <ScrollBar orientation="horizontal" />
</ScrollArea>

API reference

ScrollArea is styled on top of the Sveltery Base ScrollArea primitive, which owns the scroll position, thumb sizing and overflow detection. ScrollArea renders the viewport, a vertical ScrollBar and the corner. Add a ScrollBar with orientation="horizontal" inside it for horizontal scrolling. See the Base UI Scroll Area documentation for the behavior it ports.