Theory

A list into a grid — efficiently

In lesson 4 we got an array of pictures. Now let's turn it into a gallery — many cards in a grid. We already know how to build one card (lessons 2–3); now the point is doing it efficiently.

The naive version — in a loop, put each card straight onto the page:

pictures.forEach(pic => gallery.appendChild(createCard(pic)));   // ← many reflows

The problem: each appendChild can force the browser to reflow the layout. A hundred cards, a hundred reflows. The page "stutters".

The fix — DocumentFragment. It's a lightweight, off-screen container. You put all the cards into it, then append it to the page once — the browser reflows once:

const frag = document.createDocumentFragment();
pictures.forEach(pic => frag.appendChild(createCard(pic)));
gallery.appendChild(frag);   // ← one reflow

The second theme is image loading and reveal. The old technique for "is this element visible?" was to listen to scroll events and call getBoundingClientRect() on every pixel of scroll. That runs on the main thread hundreds of times a second and janks the page.

IntersectionObserver does the same job asynchronously, off the main thread, and only reports when an element actually crosses a threshold. We'll use it to fade pictures in as they appear, and mention how it also powers infinite scroll. (We already have free image deferral from lesson 2 — img.loading = 'lazy'.)