Overview of the Phoenix and LiveView Headless Scroll Area Component
The Mishka Chelekom Headless Scroll Area
ships zero opinionated styling
- only the semantic markup and a ScrollArea
hook that drives a custom scrollbar in place of the native one. The
thumb
is sized proportionally to the content via
--scroll-area-thumb-height
/
--scroll-area-thumb-width
, tracks the scroll
position, and is draggable; each
scrollbar
hides itself when its axis does not overflow.
orientation
selects which scrollbars render -
vertical
,
horizontal
,
or
both
. Every part - viewport, content, scrollbar,
thumb
and corner
- is addressable through a
*_class
attribute, so you style it entirely with your own Tailwind
classes while the tracking and drag behavior keep working underneath.
Hero example - vertical scroll area
A vertical scroll area with two paragraphs of text and a custom fading scrollbar that appears on hover or while scrolling.
<.scroll_area id="baseui-scroll_area-hero" orientation="vertical" class="h-[8.5rem] w-96 max-w-[calc(100vw-8rem)] bg-white dark:bg-neutral-950" viewport_class="h-full border border-neutral-950 dark:border-white focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" content_class="flex flex-col gap-4 py-2 pr-5 pl-3 text-sm leading-[1.375rem] text-neutral-950 dark:text-white" scrollbar_class="m-px flex w-4 justify-center bg-black/12 dark:bg-white/12 opacity-0 transition-opacity pointer-events-none data-[hovering]:opacity-100 data-[hovering]:pointer-events-auto data-[scrolling]:opacity-100 data-[scrolling]:duration-0 data-[scrolling]:pointer-events-auto" thumb_class="w-full h-[var(--scroll-area-thumb-height)] bg-neutral-950 dark:bg-white" > <p> Vernacular architecture is building done outside any academic tradition, and without professional guidance. It is not a particular architectural movement or style, but rather a broad category, encompassing a wide range and variety of building types, with differing methods of construction, from around the world, both historical and extant and classical and modern. Vernacular architecture constitutes 95% of the world's built environment, as estimated in 1995 by Amos Rapoport, as measured against the small percentage of new buildings every year designed by architects and built by engineers. </p> <p> This type of architecture usually serves immediate, local needs, is constrained by the materials available in its particular region and reflects local traditions and cultural practices. The study of vernacular architecture does not examine formally schooled architects, but instead that of the design skills and tradition of local builders, who were rarely given any attribution for the work. More recently, vernacular architecture has been examined by designers and the building industry in an effort to be more energy conscious with contemporary design and construction—part of a broader interest in sustainable design. </p> </.scroll_area>
Both axes - grid with corner
A scroll area that scrolls in both axes over a 10x10 grid of numbered cells, with vertical and horizontal scrollbars and a corner.
<.scroll_area id="baseui-scroll_area-both" orientation="both" class="h-80 w-80 max-w-[calc(100vw-8rem)]" viewport_class="h-full border border-neutral-950 dark:border-white focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" content_class="pt-3 pr-6 pb-6 pl-3" scrollbar_class="relative m-px flex bg-black/12 dark:bg-white/12 opacity-0 transition-opacity pointer-events-none data-[orientation=vertical]:w-4 data-[orientation=horizontal]:h-4 data-[hovering]:pointer-events-auto data-[hovering]:opacity-100 data-[scrolling]:pointer-events-auto data-[scrolling]:opacity-100 data-[scrolling]:duration-0" thumb_class="bg-neutral-950 dark:bg-white data-[orientation=vertical]:w-full data-[orientation=vertical]:h-[var(--scroll-area-thumb-height)] data-[orientation=horizontal]:h-full data-[orientation=horizontal]:w-[var(--scroll-area-thumb-width)]" > <ul class="m-0 grid list-none grid-cols-[repeat(10,6.25rem)] grid-rows-[repeat(10,6.25rem)] gap-3 p-0"> <li :for={i <- 1..100} class="flex items-center justify-center bg-neutral-200 dark:bg-neutral-800 text-sm font-bold text-neutral-600 dark:text-neutral-400" > {i} </li> </ul> </.scroll_area>
Scroll fade - edge mask
A vertical scroll area whose top and bottom edges fade out via a mask driven by the
--scroll-area-overflow-y-start
/
--scroll-area-overflow-y-end
CSS variables.
<.scroll_area id="baseui-scroll_area-scroll-fade" orientation="vertical" class="h-48 w-96 max-w-[calc(100vw-8rem)] bg-neutral-100 dark:bg-neutral-800 has-[>_[data-part=viewport]:focus-visible]:outline-2 has-[>_[data-part=viewport]:focus-visible]:outline-offset-0 has-[>_[data-part=viewport]:focus-visible]:outline-neutral-950 dark:has-[>_[data-part=viewport]:focus-visible]:outline-white" viewport_class="h-full bg-neutral-100 dark:bg-neutral-800 outline-none mask-linear-[to_bottom,transparent_0,black_min(40px,var(--scroll-area-overflow-y-start)),black_calc(100%_-_min(40px,var(--scroll-area-overflow-y-end,40px))),transparent_100%] mask-no-repeat" content_class="flex flex-col gap-4 py-2 pr-5 pl-3 text-sm leading-[1.375rem] text-neutral-950 dark:text-white" scrollbar_class="m-px flex w-4 justify-center bg-black/8 dark:bg-white/12 opacity-0 transition-opacity duration-150 pointer-events-none data-[hovering]:opacity-100 data-[hovering]:pointer-events-auto data-[scrolling]:opacity-100 data-[scrolling]:duration-0 data-[scrolling]:pointer-events-auto" thumb_class="w-full h-[var(--scroll-area-thumb-height)] bg-neutral-950 dark:bg-white" > <p> Vernacular architecture is building done outside any academic tradition, and without professional guidance. It is not a particular architectural movement or style, but rather a broad category, encompassing a wide range and variety of building types, with differing methods of construction, from around the world, both historical and extant and classical and modern. Vernacular architecture constitutes 95% of the world's built environment, as estimated in 1995 by Amos Rapoport, as measured against the small percentage of new buildings every year designed by architects and built by engineers. </p> <p> This type of architecture usually serves immediate, local needs, is constrained by the materials available in its particular region and reflects local traditions and cultural practices. The study of vernacular architecture does not examine formally schooled architects, but instead that of the design skills and tradition of local builders, who were rarely given any attribution for the work. More recently, vernacular architecture has been examined by designers and the building industry in an effort to be more energy conscious with contemporary design and construction—part of a broader interest in sustainable design. </p> </.scroll_area>
Parts & data attributes
Each part carries a stable
data-part
and a structural
chelekom-scroll_area__*
class you can target, plus live state attributes updated by the
ScrollArea
hook.
| Part | data-part | State / ARIA | Purpose |
|---|---|---|---|
| Root | - | data-orientation, data-scrolling, data-has-overflow-x, data-has-overflow-y, data-overflow-x-start, data-overflow-x-end, data-overflow-y-start, data-overflow-y-end | Wraps the whole component; carries the ScrollArea hook and exposes --scroll-area-overflow-* and --scroll-area-thumb-* CSS vars. |
| Viewport | viewport | tabindex="0", focus-visible outline | The scrollable, focusable viewport; the native scrollbar is hidden. |
| Content | content | - | Wraps the scrollable content inside the viewport. |
| Scrollbar | scrollbar | data-orientation, data-hovering, data-scrolling | The custom scrollbar track; hides itself when its axis does not overflow. |
| Thumb | thumb | data-orientation | Draggable thumb sized proportionally via --scroll-area-thumb-height/width. |
| Corner | corner | - | Fills the corner where both scrollbars meet; only rendered when orientation is both. |
Accessibility
There is no formal
WAI-ARIA APG
pattern for a scroll area. The viewport carries
tabindex="0"
so it can receive focus, and the Arrow keys, Page Up, and Page Down scroll the
focused viewport using native browser scrolling.