elements
Demos UI Feed Discuss Install
Style System
  • Style
  • Themes
  • Behaviors
Forms
  • Button
  • ButtonGroup
  • Checkbox
  • ColorPicker
  • Combobox
  • Field
  • FileUpload
  • Input
  • InputGroup
  • InputOTP
  • Label
  • NativeSelect
  • NumberInput
  • PasswordInput
  • RadioGroup
  • Select
  • Slider
  • Switch
  • TagsInput
  • Textarea
  • Toggle
  • ToggleGroup
Overlays
  • AlertDialog
  • Command
  • ContextMenu
  • Dialog
  • Drawer
  • DropdownMenu
  • HoverCard
  • Menubar
  • NavigationMenu
  • Popover
  • Sheet
  • Toast
  • Tooltip
Display
  • Accordion
  • Alert
  • AspectRatio
  • Avatar
  • Badge
  • Breadcrumb
  • Card
  • Collapsible
  • Empty
  • Item
  • Kbd
  • Pagination
  • Progress
  • Separator
  • Skeleton
  • Spinner
  • Table
  • Tabs
  • Tree
Layout
  • Carousel
  • Resizable
  • ScrollArea
  • Sidebar
Dates
  • Calendar
  • DatePicker
  • DateRangePicker
  • TimePicker
Data
  • AreaChart
  • BarChart
  • Chart
  • DataTable
  • Kanban
  • LineChart
  • PieChart
  • RadarChart
  • RadialChart
  • VirtualList
Chat
  • Attachment
  • Message
  • MessageList
  • PromptInput
Elements UI / Layout / ScrollArea

ScrollArea

A scroll container with thin, themed scrollbars over native scrolling.

Vertical

Hover or scroll to see the bar. Tab focuses the list; arrows and End scroll it.

Tags

v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48
v1.2.0-beta.47
v1.2.0-beta.46
v1.2.0-beta.45
v1.2.0-beta.44
v1.2.0-beta.43
v1.2.0-beta.42
v1.2.0-beta.41
v1.2.0-beta.40
v1.2.0-beta.39
v1.2.0-beta.38
v1.2.0-beta.37
v1.2.0-beta.36
v1.2.0-beta.35
v1.2.0-beta.34
v1.2.0-beta.33
v1.2.0-beta.32
v1.2.0-beta.31
v1.2.0-beta.30
v1.2.0-beta.29
v1.2.0-beta.28
v1.2.0-beta.27
v1.2.0-beta.26
v1.2.0-beta.25
v1.2.0-beta.24
v1.2.0-beta.23
v1.2.0-beta.22
v1.2.0-beta.21
v1.2.0-beta.20
v1.2.0-beta.19
v1.2.0-beta.18
v1.2.0-beta.17
v1.2.0-beta.16
v1.2.0-beta.15
v1.2.0-beta.14
v1.2.0-beta.13
v1.2.0-beta.12
v1.2.0-beta.11
v1.2.0-beta.10
v1.2.0-beta.9
v1.2.0-beta.8
v1.2.0-beta.7
v1.2.0-beta.6
v1.2.0-beta.5
v1.2.0-beta.4
v1.2.0-beta.3
v1.2.0-beta.2
v1.2.0-beta.1
scroll events: 0
Code
<ScrollArea class="tags" label="Tags">
  <div class="list">
    <h4>Tags</h4>
    <div class="tag" e:for={tag of tags}>{tag}</div>
  </div>
</ScrollArea>

Usage

import { ScrollArea } from "@elements/ui/scroll-area";

<ScrollArea class="tags" label="Tags">
  <h4>Tags</h4>
  <div e:for={tag of tags}>{tag}</div>
</ScrollArea>

<ScrollArea orientation="horizontal" type="always">
  <div class="row">...</div>
</ScrollArea>

Examples

Horizontal

orientation horizontal with type always: the bar stays, the content scrolls sideways.

Photo by Ornella Binni
Photo by Tom Byrom
Photo by Vladimir Malyavko
Photo by Sandra Ortiz
Photo by Kenji Aoki
Code
<ScrollArea orientation="horizontal" type="always" class="gallery" label="Artwork">
  <div class="row">
    <figure e:for={work of works}>...</figure>
  </div>
</ScrollArea>

Types

When the bars show: hover (default), scroll, auto and always.

type="hover"
v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48
v1.2.0-beta.47
v1.2.0-beta.46
v1.2.0-beta.45
v1.2.0-beta.44
v1.2.0-beta.43
v1.2.0-beta.42
v1.2.0-beta.41
v1.2.0-beta.40
v1.2.0-beta.39
v1.2.0-beta.38
v1.2.0-beta.37
v1.2.0-beta.36
v1.2.0-beta.35
v1.2.0-beta.34
v1.2.0-beta.33
v1.2.0-beta.32
v1.2.0-beta.31
type="scroll"
v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48
v1.2.0-beta.47
v1.2.0-beta.46
v1.2.0-beta.45
v1.2.0-beta.44
v1.2.0-beta.43
v1.2.0-beta.42
v1.2.0-beta.41
v1.2.0-beta.40
v1.2.0-beta.39
v1.2.0-beta.38
v1.2.0-beta.37
v1.2.0-beta.36
v1.2.0-beta.35
v1.2.0-beta.34
v1.2.0-beta.33
v1.2.0-beta.32
v1.2.0-beta.31
type="auto"
v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48
v1.2.0-beta.47
v1.2.0-beta.46
v1.2.0-beta.45
v1.2.0-beta.44
v1.2.0-beta.43
v1.2.0-beta.42
v1.2.0-beta.41
v1.2.0-beta.40
v1.2.0-beta.39
v1.2.0-beta.38
v1.2.0-beta.37
v1.2.0-beta.36
v1.2.0-beta.35
v1.2.0-beta.34
v1.2.0-beta.33
v1.2.0-beta.32
v1.2.0-beta.31
type="always"
v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48
v1.2.0-beta.47
v1.2.0-beta.46
v1.2.0-beta.45
v1.2.0-beta.44
v1.2.0-beta.43
v1.2.0-beta.42
v1.2.0-beta.41
v1.2.0-beta.40
v1.2.0-beta.39
v1.2.0-beta.38
v1.2.0-beta.37
v1.2.0-beta.36
v1.2.0-beta.35
v1.2.0-beta.34
v1.2.0-beta.33
v1.2.0-beta.32
v1.2.0-beta.31
Code
<ScrollArea type="hover">...</ScrollArea>    <!-- scrolling or pointer over -->
<ScrollArea type="scroll">...</ScrollArea>   <!-- only while scrolling -->
<ScrollArea type="auto">...</ScrollArea>     <!-- whenever it overflows -->
<ScrollArea type="always">...</ScrollArea>   <!-- always -->

Both axes

Two bars and a corner where they meet. The vertical bar stops above the corner.

1:1
1:2
1:3
1:4
1:5
1:6
1:7
1:8
1:9
1:10
1:11
1:12
2:1
2:2
2:3
2:4
2:5
2:6
2:7
2:8
2:9
2:10
2:11
2:12
3:1
3:2
3:3
3:4
3:5
3:6
3:7
3:8
3:9
3:10
3:11
3:12
4:1
4:2
4:3
4:4
4:5
4:6
4:7
4:8
4:9
4:10
4:11
4:12
5:1
5:2
5:3
5:4
5:5
5:6
5:7
5:8
5:9
5:10
5:11
5:12
6:1
6:2
6:3
6:4
6:5
6:6
6:7
6:8
6:9
6:10
6:11
6:12
7:1
7:2
7:3
7:4
7:5
7:6
7:7
7:8
7:9
7:10
7:11
7:12
8:1
8:2
8:3
8:4
8:5
8:6
8:7
8:8
8:9
8:10
8:11
8:12
9:1
9:2
9:3
9:4
9:5
9:6
9:7
9:8
9:9
9:10
9:11
9:12
10:1
10:2
10:3
10:4
10:5
10:6
10:7
10:8
10:9
10:10
10:11
10:12
11:1
11:2
11:3
11:4
11:5
11:6
11:7
11:8
11:9
11:10
11:11
11:12
12:1
12:2
12:3
12:4
12:5
12:6
12:7
12:8
12:9
12:10
12:11
12:12
13:1
13:2
13:3
13:4
13:5
13:6
13:7
13:8
13:9
13:10
13:11
13:12
14:1
14:2
14:3
14:4
14:5
14:6
14:7
14:8
14:9
14:10
14:11
14:12
15:1
15:2
15:3
15:4
15:5
15:6
15:7
15:8
15:9
15:10
15:11
15:12
16:1
16:2
16:3
16:4
16:5
16:6
16:7
16:8
16:9
16:10
16:11
16:12
17:1
17:2
17:3
17:4
17:5
17:6
17:7
17:8
17:9
17:10
17:11
17:12
18:1
18:2
18:3
18:4
18:5
18:6
18:7
18:8
18:9
18:10
18:11
18:12
19:1
19:2
19:3
19:4
19:5
19:6
19:7
19:8
19:9
19:10
19:11
19:12
20:1
20:2
20:3
20:4
20:5
20:6
20:7
20:8
20:9
20:10
20:11
20:12
Code
<ScrollArea orientation="both" type="auto" class="grid">
  <table>...</table>
</ScrollArea>

Growing content

type auto shows the bar once the content overflows, measured as it changes.

Item 1
Item 2
Item 3
Code
<ScrollArea type="auto" class="list">
  <div e:for={i of items}>Item {i}</div>
</ScrollArea>
<Button onclick={() => items++}>Add item</Button>

Right to left

Under rtl the vertical bar sits on the left and horizontal scrolling starts at the right. The button switches the list's direction.

واحد
اثنان
ثلاثة
أربعة
خمسة
ستة
سبعة
ثمانية
تسعة
عشرة
أحد عشر
اثنا عشر
واحد
اثنان
ثلاثة
أربعة
خمسة
ستة
Code
<ScrollArea dir={state.dir} type="always">...</ScrollArea>
<Button onclick={() => state.dir = state.dir === "rtl" ? "ltr" : "rtl"}>Direction</Button>

Scroll fade

The viewport carries each edge's overflow in px (--scroll-area-overflow-y-start and -end), here driving a mask that fades the edges with more to scroll. overflowEdgeThreshold sets when data-overflow-y-start turns on.

v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48
v1.2.0-beta.47
v1.2.0-beta.46
v1.2.0-beta.45
v1.2.0-beta.44
v1.2.0-beta.43
v1.2.0-beta.42
v1.2.0-beta.41
v1.2.0-beta.40
v1.2.0-beta.39
v1.2.0-beta.38
v1.2.0-beta.37
v1.2.0-beta.36
v1.2.0-beta.35
v1.2.0-beta.34
v1.2.0-beta.33
v1.2.0-beta.32
v1.2.0-beta.31
Code
<!-- The viewport carries each edge's overflow in px; mask the content with it.
     overflowEdgeThreshold keeps data-overflow-y-start off for the first 8px. -->
<ScrollArea type="auto" overflowEdgeThreshold={8} class="fade">...</ScrollArea>

.fade .scroll-area-viewport {
  mask-image: linear-gradient(to bottom,
    transparent 0, black min(var(--space-10), var(--scroll-area-overflow-y-start)),
    black calc(100% - min(var(--space-10), var(--scroll-area-overflow-y-end))), transparent 100%);
}

Per-edge threshold

overflowEdgeThreshold also takes an object with xStart, xEnd, yStart and yEnd. Here the top edge turns on at once (yStart 0) and the bottom one turns off 40px before the end (yEnd 40).

v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48
v1.2.0-beta.47
v1.2.0-beta.46
v1.2.0-beta.45
v1.2.0-beta.44
v1.2.0-beta.43
v1.2.0-beta.42
v1.2.0-beta.41
v1.2.0-beta.40
v1.2.0-beta.39
v1.2.0-beta.38
v1.2.0-beta.37
v1.2.0-beta.36
v1.2.0-beta.35
v1.2.0-beta.34
v1.2.0-beta.33
v1.2.0-beta.32
v1.2.0-beta.31
Code
<!-- A threshold per edge: the top flag turns on at once, the bottom one
     turns off 40px before the end. -->
<ScrollArea type="auto" overflowEdgeThreshold={{ yStart: 0, yEnd: 40 }} class="fade">...</ScrollArea>
Reference ScrollArea in the manual Every part, attribute, slot, key and data attribute.
Prev ResizableNext Sidebar
Product
Manual Pricing Compare
Company
History Contact
Legal
Privacy Policy Acceptable Use Terms License Agreement
© Elements Dev Corporation 2026