Skip to main content
RapidDev - Software Development Agency
bubble-tutorial

How to build infinite scroll in Bubble

Infinite scroll in Bubble is achieved by configuring a Repeating Group with vertical scrolling and scroll detection. As the user reaches the bottom, additional items load automatically by increasing the data source's item count. This approach avoids pagination buttons and creates a seamless social-media-style feed experience while keeping performance manageable.

What you'll learn

  • How to configure a Repeating Group for infinite scrolling
  • How to detect scroll position and trigger loading more items
  • How to optimize performance with large datasets using pagination offsets
  • How to add a loading indicator while new items load
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read15-20 minAll Bubble plansMarch 2026RapidDev Engineering Team
TL;DR

Infinite scroll in Bubble is achieved by configuring a Repeating Group with vertical scrolling and scroll detection. As the user reaches the bottom, additional items load automatically by increasing the data source's item count. This approach avoids pagination buttons and creates a seamless social-media-style feed experience while keeping performance manageable.

Build Infinite Scroll in Bubble

This tutorial shows you how to create a continuous scroll (infinite scroll) feature in your Bubble app. Instead of pagination buttons, content loads automatically as users scroll down. This is ideal for feeds, product listings, and content-heavy pages. You will configure a Repeating Group, set up scroll detection, and implement progressive data loading.

Prerequisites

  • A Bubble account with an active app
  • A Data Type with enough records to demonstrate scrolling (at least 30-50 items)
  • Basic understanding of Repeating Groups and data sources in Bubble
  • Familiarity with Custom States

Step-by-step guide

1

Set Up the Repeating Group with Ext. Vertical Scrolling

In the Design tab, add a Repeating Group element. Set the Type of content to your Data Type (e.g., Post). Under Layout, choose 'Ext. vertical scrolling'. Set the number of rows to your initial load count — for example, 10. Set the Data source to 'Do a Search for Posts' sorted by Created Date descending. Configure the cell layout with the elements you want to display per item (text, images, etc.).

Pro tip: Set the Repeating Group to fill the page height. The 'Ext. vertical scrolling' option allows the RG to grow as items are added, unlike fixed-height scrolling which constrains visible rows.

Expected result: A Repeating Group displays the first batch of items with vertical scrolling enabled.

2

Create a Custom State to Track the Item Count

Click on the page element (or the Repeating Group itself) and add a Custom State. Name it 'items_to_show' with type 'number'. Set a default value of 10 (or whatever your initial batch size is). Update the Repeating Group's data source to use this state: 'Do a Search for Posts:items until #(page's items_to_show)' sorted by Created Date descending. This limits how many items the RG displays based on the state value.

Expected result: The Repeating Group shows only the number of items specified by the items_to_show Custom State.

3

Add Scroll Detection to Load More Items

Add a small Group element at the very bottom of the Repeating Group's last cell — or below the Repeating Group — and name it 'ScrollTrigger'. Make it 1 pixel tall and transparent. Create a workflow: 'Do when condition is true' with the condition 'RepeatingGroup Posts:last item is visible' (if supported by the RG) or use a 'When ScrollTrigger is visible' event via a visibility-detection plugin. In the workflow actions, add: 'Set state of page — items_to_show = page's items_to_show + 10'. This increases the item count by 10 each time the user scrolls near the bottom.

Pro tip: Some Bubble plans and RG configurations support the ':last item is visible' condition natively. If not, use the 'Repeating Group Scroll Position' plugin or the Toolbox plugin's JavaScript approach with IntersectionObserver.

Expected result: Scrolling to the bottom automatically loads 10 more items into the Repeating Group.

4

Add a Loading Indicator

Place a Group below the Repeating Group containing a loading spinner image or text 'Loading more...'. Set this group to be conditionally visible: 'This element is visible when page's items_to_show < Do a Search for Posts:count'. This means the loader shows only when there are more items to load. Once all items are loaded, the loader disappears. Optionally, add a 'No more items' text that shows when all items are displayed.

Expected result: A loading indicator appears while new items load and disappears when all data has been loaded.

5

Optimize Performance for Large Datasets

For datasets with thousands of items, loading all of them into memory is impractical. Instead of using :items until, adjust the Search's constraints to fetch only the current window of items. Create an additional Custom State 'current_offset' (number, default 0). Set the data source to 'Do a Search for Posts:items from current_offset:items until 10'. When loading more, increment current_offset by 10. Also add Search constraints to limit the query scope — for example, only posts from the last 30 days. Consider storing the list in a Custom State (list type) and appending new search results to it.

Pro tip: Bubble does not virtualize Repeating Group rows — every loaded item remains in the DOM. For very large feeds (hundreds of items), consider implementing a manual 'Load More' button instead of true infinite scroll to give users control.

Expected result: The infinite scroll works efficiently even with large datasets, loading items in small batches.

Complete working example

Workflow summary
1PAGE: feed
2
3CUSTOM STATES (on page):
4- items_to_show (number, default: 10)
5- is_loading (yes/no, default: no)
6- all_loaded (yes/no, default: no)
7
8ELEMENTS:
9- RepeatingGroup Posts
10 - Type of content: Post
11 - Layout: Ext. vertical scrolling
12 - Data source: Search for Posts (sorted by Created Date desc) :items until page's items_to_show
13 - Cell: Post title, author, date, content preview, image
14
15- Group LoadingIndicator (below RG)
16 - Visible when: page's is_loading is yes
17 - Contains: Spinning icon + text "Loading more..."
18
19- Group AllLoaded (below RG)
20 - Visible when: page's all_loaded is yes
21 - Contains: Text "You've seen all posts"
22
23WORKFLOWS:
241. Do when condition is true:
25 Condition: RepeatingGroup Posts is scrolled to the bottom
26 AND page's is_loading is no
27 AND page's all_loaded is no
28 Set state: is_loading = yes
29 Add a pause (500ms)
30 Set state: items_to_show = items_to_show + 10
31 Set state: is_loading = no
32 Only when items_to_show >= Search for Posts:count:
33 Set state: all_loaded = yes
34
35PERFORMANCE NOTES:
36- Keep initial load to 10-15 items
37- Increment by 10 items per scroll trigger
38- Use Search constraints (date ranges, categories) to limit total dataset
39- Avoid nested searches inside RG cells
40- Consider 'Load More' button for datasets exceeding 200 items

Common mistakes when building infinite scroll in Bubble

Why it's a problem: Loading all items at once and hiding overflow

How to avoid: Use progressive loading with a Custom State controlling the item count, increasing it in small increments as the user scrolls.

Why it's a problem: Not adding a termination condition for loading

How to avoid: Compare the current items_to_show value against the total search count. When items_to_show >= total count, set an 'all_loaded' state to stop triggering.

Why it's a problem: Using :filtered instead of Search constraints for large lists

How to avoid: Apply all filters as Search constraints within the 'Do a Search for' dialog.

Best practices

  • Start with 10-15 items on initial load to keep the first page render fast.
  • Add a 300-500ms debounce delay before loading more items to prevent rapid-fire triggers from fast scrolling.
  • Show a loading spinner while new items are being fetched to set user expectations.
  • Display a clear 'end of list' message when all items have been loaded.
  • Use Search constraints instead of :filtered to keep server-side queries efficient.
  • Test with realistic data volumes — infinite scroll that works with 50 items may fail with 5,000.
  • For mobile users, keep cell heights reasonable and minimize heavy images per cell to prevent memory issues.
  • Consider adding a 'Back to top' floating button for long scrolling pages.

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I'm building a social feed in Bubble.io and want infinite scroll instead of pagination. I have a Post data type with title, content, author, and created_date. How do I set up a Repeating Group that loads 10 posts at a time as the user scrolls down, with a loading indicator and end-of-list message?

Bubble Prompt

Create a feed page with a Repeating Group showing Posts. Implement infinite scroll that loads 10 items initially and 10 more each time the user scrolls to the bottom. Add a loading spinner and a message when all posts are shown.

Frequently asked questions

Does Bubble support native infinite scroll without plugins?

Bubble's Repeating Group with 'Ext. vertical scrolling' provides basic scroll behavior, but true infinite loading (fetching more data on scroll) requires Custom States and workflow logic. Some plugins like 'Repeating Group Scroll Position' make detection easier.

How many items can I load before performance degrades?

Performance depends on cell complexity, but generally 100-200 items is the practical limit before browsers slow down. Bubble does not virtualize rows, so every loaded item stays in memory. For larger datasets, consider a manual 'Load More' button.

Can I use infinite scroll with filtered or searched data?

Yes. Apply your search filters as Search constraints in the data source. The infinite scroll logic works the same — the items_to_show state controls how many filtered results are displayed, and the total count reflects the filtered dataset.

How do I handle the scroll position when a user navigates back to the page?

Bubble does not preserve scroll position across page navigation by default. Store the last viewed item count in a URL parameter or the database, and on page load, set items_to_show to that saved value.

Should I use infinite scroll or pagination for my app?

Infinite scroll is best for browse/discovery feeds (social posts, products). Pagination is better for structured data (search results, admin tables) where users need to reach specific pages. For complex projects, RapidDev can help you choose the right approach.

Can I combine infinite scroll with pull-to-refresh on mobile?

Bubble's web-based apps do not have native pull-to-refresh. You can add a 'Refresh' button at the top that resets the items_to_show state and re-runs the search. For true pull-to-refresh, you would need a custom JavaScript solution using touch events.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.