Skip to the solution
MediumFrontend12 min read

Build Infinite Scroll with IntersectionObserver & Skeleton

714 views

The problem

Question presented to candidate: "Our social feed loads 10 posts per request. Build it so the next page loads automatically before the user reaches the end, but without listening to scroll events. While a page is loading, show skeleton cards in place of the posts that are coming, and make sure nothing on the page jumps when the real posts arrive."

Requirements:

  • A 460px scrollable feed of 96px post cards; 50 posts in total, 10 per page (simulated API, 600ms per request, page 3 fails once).
  • Use IntersectionObserver on a sentinel element after the last card, with the feed as the root and a 300px bottom margin so loading starts early.
  • Never start a second request while one is in flight, even if the observer reports the sentinel more than once.
  • Show 4 skeleton cards on the first load and 2 below the existing posts on later loads, each the same size as a real card.
  • Show a Retry button on failure and "No more posts" at the end; stop observing in both cases.
  • If the first page does not fill the feed, keep loading without any scrolling.
  • Announce loading and loaded states to screen readers, hide skeletons from them, and respect reduced motion.

What a strong answer should cover:

  • The sentinel pattern: observe one element at the end instead of computing distances on every scroll event, and root plus rootMargin to trigger early.
  • That observe() reports the current state once, which handles short pages for free when the sentinel is re-observed after each page.
  • A synchronous in-flight guard, and creating or disconnecting the observer on mount, unmount and state change so no observer leaks.
  • Skeletons with the same dimensions as real content to avoid layout shift, aria-hidden on them, a polite live region, and prefers-reduced-motion for the shimmer.
  • Error and end states that stop observing, and a manual retry.
  • How it compares with a scroll listener, and when virtualization becomes necessary.

Clarifying questions expected:

  • "Does the feed scroll inside its own container or with the window? That decides the observer root."
  • "How early should the next page start loading?"
  • "Do posts have a fixed height, or do the skeletons need to approximate variable content?"

Code / implementation expected: Yes. A feed component with an IntersectionObserver sentinel, a guarded fetch, skeleton cards, and loading, error and end states, using a simulated API.

  • React
  • Infinite Scroll
  • IntersectionObserver
  • Skeleton

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

12 min read · 9 sections

React solution

Every file of the working solution. Open it in the playground to run and change it.

ReactComplete solution
import Feed from "./src/components/Feed";

export default function App() {
  return (
    <main className="app">
      <h1>Feed (IntersectionObserver + skeletons)</h1>
      <Feed />
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 47 of 107 in Machine coding

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextMedium

Build an Accessible Modal with Focus Trap & Scroll Lock

Continue