Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelogApp ShellAspect GridAuth ShellCenterContainerDashboard GridFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbarAnchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkStepper NavTabsTop BarTree ViewAccordionAspect RatioAvatarAvatar GroupCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSkeletonSpinnerStackVideoVirtual ListActivity HeatmapAnimated NumberBadgeBar ListChartClockComparisonCountdown TimerData GridDescription ListDiffGaugeJSON TreeKanbanLevel MeterListMeterSparklineStatStepperTagTimelineUptimeValue CardWaveformBlockquoteCode BlockCode GroupGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriterButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerField ListFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree SelectAlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuHover CardLoading OverlayNotification PanelPopoverProgressSheetToastTooltip
ARC UIARC Radiant Components
v4.9DocsComponentsTokensSynthesizer
Getting StartedFrameworksServer RenderingDesign TokensThemingTheme SynthesizerTypographyUtilitiesAll ComponentsAccessibilityBrowser SupportChangelogContributingStatsApp ShellAspect GridAuth ShellCenterContainerDashboard GridFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbarAnchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkStepper NavTabsTop BarTree ViewAccordionAspect RatioAvatarAvatar GroupCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSkeletonSpinnerStackVideoVirtual ListActivity HeatmapAnimated NumberBadgeBar ListChartClockComparisonCountdown TimerData GridDescription ListDiffGaugeJSON TreeKanbanLevel MeterListMeterSparklineStatStepperTagTimelineUptimeValue CardWaveformBlockquoteCode BlockCode GroupGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriterButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerField ListFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree SelectAlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuHover CardLoading OverlayNotification PanelPopoverProgressSheetToastTooltip

Infinite Scroll

Intersection Observer-powered container that fires a load event when the user scrolls near the bottom, with built-in loading spinner and end-of-list state.

ComponentsInfinite Scroll
contentinteractive
<arc-infinite-scroll>

Overview

InfiniteScroll wraps your content in a feed container and watches for when the user approaches the bottom using an Intersection Observer sentinel element. When the sentinel enters the viewport (plus a configurable `threshold` margin), the component fires an `arc-load-more` event, signalling your application to fetch and append the next batch of items. This eliminates the need for manual scroll listeners or pagination button clicks. While data is being fetched, set the `loading` prop to `true` to display a centered spinner in the footer area. The component automatically suppresses additional `arc-load-more` events while loading is active, preventing duplicate fetch requests. Once your data arrives, reset `loading` to `false` and the sentinel resumes observation. When all data has been loaded, set the `finished` prop to `true`. The sentinel is removed and replaced with a "No more items" text indicator, and the Intersection Observer is disconnected. The container uses `aria-busy` to communicate loading state to assistive technologies. If your items are self-contained entries (e.g. posts), slot them as `<article>` elements and add `role="feed"` to the component to opt into the ARIA feed pattern.

Guidelines

When to use

  • Set `loading` to `true` immediately when you begin fetching data, and reset it to `false` when data arrives
  • Set `finished` to `true` when the API indicates no more pages remain, so the observer disconnects
  • Use a reasonable `threshold` (100-300px) so content loads before users hit the bottom and see a gap
  • Place InfiniteScroll inside a scrollable parent or let the page itself be the scroll container
  • Append new items as direct children of the component. They render in the default slot

When not to use

  • Do not leave `loading` as `true` indefinitely. This blocks further load events and leaves the spinner visible
  • Do not use InfiniteScroll for small, fixed datasets. Standard pagination or a simple list fits better
  • Do not set `threshold` to 0. The user will see a flash of empty space before content loads
  • Do not nest multiple InfiniteScroll components. Their observers may conflict
  • Avoid using InfiniteScroll without providing a way to reach footer content, since it pushes the footer down continuously

Features

  • Intersection Observer-based sentinel that fires `arc-load-more` when the user nears the content bottom
  • Configurable `threshold` prop (in pixels) to control how far in advance the load event triggers
  • Built-in `arc-spinner` displayed in the footer when `loading` is `true`
  • Automatic suppression of duplicate load events while loading is in progress
  • End-of-list state via the `finished` prop: removes the sentinel and shows "No more items" text
  • ARIA `aria-busy` for accessible loading communication
  • Observer automatically disconnects and reconnects when `finished` or `disabled` change
  • Disabled state at 40% opacity with pointer events blocked

Preview

Usage

This component requires JavaScript. No pure HTML/CSS version is available. Use the Web Component directly or a framework wrapper.

<arc-infinite-scroll id="feed" threshold="200">
  <!-- Items appended here -->
</arc-infinite-scroll>

<script>
  const feed = document.getElementById('feed');
  let page = 1;

  feed.addEventListener('arc-load-more', async () => {
    feed.loading = true;
    const items = await fetchPage(page++);
    items.forEach(item => feed.appendChild(createItemEl(item)));
    feed.loading = false;
    if (!items.length) feed.finished = true;
  });
</script>

API

thresholdnumber200
Distance in pixels from the bottom of the content at which arc-load-more fires. Controls how eagerly new data is requested.
loadingbooleanfalse
When true, displays a spinner in the footer and suppresses additional arc-load-more events.
finishedbooleanfalse
When true, disconnects the observer and displays "No more items" text in the footer.
disabledbooleanfalse
Disables the component, disconnects the observer, and reduces opacity to 40%.

Events

arc-load-more
Fired when the scroll sentinel enters the viewport, signaling more content should load

See Also