Back

InfiniteScroll

How It Works

The InfiniteScroll component places a sentinel div at the bottom of a list. When the sentinel enters the viewport (with a 200px early trigger), it fires an HTMX GET request. The server responds with new items and a new sentinel (with Page + 1), which replaces the old sentinel via hx-swap="outerHTML". When there are no more items, the server returns nothing — the sentinel disappears and loading stops.

Sentinel (Static Demo)

The sentinel below shows the loading state. In production the HTMX request fires automatically.

1

Item 1

Loaded from server

2

Item 2

Loaded from server

3

Item 3

Loaded from server

4

Item 4

Loaded from server

5

Item 5

Loaded from server

6

Item 6

Loaded from server

Loading…

Usage

// In your list page (initial load):
<ul id="items">
    for _, item := range items {
        <li>{ item.Title }</li>
    }
</ul>
@feedback.InfiniteScroll(feedback.InfiniteScrollProps{
    LoadURL: "/api/items",
    Page:    2,          // next page to load
    Loading: true,       // show spinner while loading
})

// HTMX partial handler (returns items + new sentinel):
// GET /api/items?page=2
for _, item := range page2Items {
    <li hx-swap-oob="beforeend:#items">{ item.Title }</li>
}
if hasMore {
    @feedback.InfiniteScroll(feedback.InfiniteScrollProps{
        LoadURL: "/api/items",
        Page:    3,
    })
}