Skip to main content

rc-scroller

Native scroll region with an optional centered content layout and fullbleed track. The custom element host is the scrollport, so native scrolling APIs, events, restoration, and observers work without reaching into shadow DOM.

Package
@rcarls/rc-scroller
Element
<rc-scroller>
Native dependency
Custom element host is the native scrollport
State model
Declarative axis and layout
Main events
scroll (native)

Installation

npm install @rcarls/rc-scroller
import '@rcarls/rc-scroller/define';

Markup

<rc-scroller layout="content" role="region" aria-label="Recipes">
<header data-rc-scroller-span="fullbleed">Recipes</header>
<article>Apple pie</article>
</rc-scroller>

Give the host a definite block size, or place it in a layout that provides one, when it should scroll. axis accepts block (the default), inline, or both. The component does not add a landmark, accessible name, or tab stop; authors add those semantics only when the surrounding document needs them.

Live demo

Content layout

Set layout="content" to place direct children on a centered content track. The track uses --rc-scroller-content-padding-inline for its minimum gutters and --rc-scroller-content-max-inline-size for its maximum width. A direct child with data-rc-scroller-span="fullbleed" spans the entire available inline size while preserving source order.

Without layout="content", the component only establishes a native scrollport. It does not impose padding or child layout.

Scroll-boundary state

at-block-start, at-block-end, at-inline-start, and at-inline-end are reflected, read-only attributes: present when scrolled to (within a few pixels of) that edge on an enabled axis, or when that axis isn't scrollable at all (nothing more to reveal counts as already at both of its edges). Style an edge affordance from outside the shadow root by targeting the attribute directly, for example an edge-fade mask on an inline scroller:

rc-scroller[axis='inline'] {
mask-image: linear-gradient(
to right,
transparent,
black 24px,
black calc(100% - 24px),
transparent
);
}

rc-scroller[axis='inline'][at-inline-start] {
mask-image: linear-gradient(to right, black calc(100% - 24px), transparent);
}

rc-scroller[axis='inline'][at-inline-end] {
mask-image: linear-gradient(to right, transparent, black 24px);
}

The component only tracks and reflects this state: it makes no visual decision of its own about how, or whether, to show it.

API

Properties

PropertyMarkupTypeDefaultDescription
axisaxisRCScrollerAxis'block'Scroll axis.
layoutlayoutRCScrollerLayout'none'Optional child layout.
atBlockStartat-block-startbooleantrueReflected, computed. See the class doc comment.
atBlockEndat-block-endbooleantrueReflected, computed. See the class doc comment.
atInlineStartat-inline-startbooleantrueReflected, computed. See the class doc comment.
atInlineEndat-inline-endbooleantrueReflected, computed. See the class doc comment.

Methods

No public methods are documented in the custom elements manifest.

Events

No custom events are documented in the custom elements manifest.

Slots

NameDescription
(default)Scrollable content.

CSS Custom Properties

PropertyDefaultDescription
--rc-scroller-overscroll-behaviorcontainOverscroll behavior on enabled axes.
--rc-scroller-overflow-anchorautoBrowser scroll anchoring behavior.
--rc-scroller-scrollbar-widthautoScrollbar width.
--rc-scroller-scrollbar-colorautoScrollbar thumb and track colors.
--rc-scroller-content-padding-inline1remMinimum inline gutter in content layout.
--rc-scroller-content-max-inline-size100%Maximum width of the content track.
--rc-scroller-content-row-gap0Gap between rows in content layout.

CSS Parts

PartDescription
contentWrapper for the default slot and optional layout grid.