I guess you can just start loading a first batch, add an intersection observer to the last 3 elements (if you have 3 lanes) and then when one of those intersects you simply start fetching the next.
Aahh. The way you phrased your question was pretty ambiguous.
The other posters have good answers. One thing to consider for a smooth interaction would be to eagerly load the next x elements before they scroll into view.
Yeah I’d assume you’d eagerly load enough to make sure everything gets at least partially into the viewport, and maybe a fee more to optimize for network latency. And then perhaps track elements whose trailing ends are not in the viewport, and load more once those become fully visible?