A scroll container with thin, themed scrollbars over native scrolling.
Example
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>
Parts
| Part |
What it is |
ScrollArea |
The root. Give it a height or max-height through class; the viewport fills it. |
.scroll-area-viewport |
The native scroller. Takes attrs; query it to scroll from code. |
.scroll-area-scrollbar |
One track per axis, drawn over the content edge. data-orientation, data-state. |
.scroll-area-thumb |
The draggable thumb. Its length is viewport / content of the track. |
.scroll-area-corner |
The square where both bars meet, shown while both show. |
Attributes
| Attribute |
Type |
Default |
Description |
type |
"auto" | "always" | "scroll" | "hover" |
"hover" |
When the bars show. auto: while the axis overflows. always: always (the thumb only with overflow). scroll: while scrolling. hover: while scrolling or while the pointer is over the area. |
scrollHideDelay |
number |
600 |
For scroll and hover: milliseconds after the last scroll or pointer leave before the bars hide. |
orientation |
"vertical" | "horizontal" | "both" |
"vertical" |
Which scrollbars render; the viewport scrolls on those axes only. |
overflowEdgeThreshold |
number | { xStart?, xEnd?, yStart?, yEnd? } |
0 |
px of overflow an edge needs before its data-overflow-*-start or -end attribute turns on. |
dir |
"ltr" | "rtl" | "" |
"" |
Reading direction; empty inherits. Under rtl the vertical bar is on the left. |
label |
string |
"" |
Names the viewport and makes it a region landmark. |
class |
string |
"" |
Extra classes on the root. |
attrs |
Record<string, string | number | boolean | undefined> |
{} |
Attributes for the viewport: id, data-testid, aria-*. |
onScroll |
(e: Event) => void |
() => {} |
The viewport's scroll event. |
Slots
| Slot |
Content |
default |
The content that scrolls. |
Keyboard
| Keys |
Action |
Tab |
Focuses the viewport while it overflows, so it can be scrolled from the keyboard. |
ArrowUp / ArrowDown / ArrowLeft / ArrowRight |
Scrolls by a line (native). |
PageUp / PageDown / Space |
Scrolls by a page (native). |
Home / End |
Scrolls to the start or end (native). |
Data attributes
| Attribute |
Values |
On |
Description |
data-state |
"visible" | "hidden" |
.scroll-area-scrollbar, .scroll-area-thumb, .scroll-area-corner |
|
data-orientation |
"vertical" | "horizontal" |
.scroll-area-scrollbar |
On the root also "both". |
data-type |
the type |
root |
|
data-has-overflow-x, data-has-overflow-y |
present |
root, viewport, content, scrollbar |
While that axis overflows. |
data-overflow-x-start, -x-end, -y-start, -y-end |
present |
root, viewport, content, scrollbar |
While there is more to scroll past that edge (beyond overflowEdgeThreshold). |
data-scrolling |
present |
root, viewport, content, scrollbar, thumb |
While scrolling, by any input. |
data-hovering |
present |
.scroll-area-scrollbar |
While the pointer is over the area. |
data-orientation |
"vertical" | "horizontal" |
.scroll-area-thumb |
|
--scroll-area-overflow-x-start, -x-end, -y-start, -y-end |
px |
.scroll-area-viewport |
Distance left to scroll past each edge. Not inherited; a child opts in with inherit. |
--scroll-area-thumb-height, --scroll-area-thumb-width |
px |
.scroll-area-scrollbar |
|
data-dragging |
present |
.scroll-area-scrollbar |
While the thumb is dragged. |
--scroll-area-thumb-size |
px |
.scroll-area-thumb |
|
--scroll-area-corner-width, --scroll-area-corner-height |
px |
root |
|
Accessibility
- Scrolling is the browser's own, so every keyboard, screen reader and find-in-page path works unchanged.
- The viewport is a tab stop while it overflows (WCAG 2.1.1); the focus ring is drawn on the root.
- Scrollbars and the corner are aria-hidden; label names the viewport as a region.
See also