🎮 IntersectionObserver: catch visibility, not scroll pixels

Scroll the stage below and watch isIntersecting and intersectionRatio update in the log — only when the target's visibility actually crosses a line you set, never on every scroll frame. Drag threshold and root margin to change exactly when that happens, or flip lazy-load mode to see the real one-shot pattern: fade in once, then unobserve().

1 Controls
Threshold — 0.00

The fraction of the box that must be visible before the callback reports isIntersecting: true. 0 fires at the first visible pixel; 1 waits for the whole box.

Root margin (bottom) — 0px

Grows or shrinks the stage's own visible edge for intersection purposes. Positive fires before the box reaches the fold (preloading); negative delays it.

2 Scroll the stage
↓ scroll down to bring the target into view ↓
Target box
(the observed element)
You're past it now — scroll back up to see it exit.
isIntersecting
intersectionRatio 0.00
visible fraction
Ready — scroll the stage above.
3 Live entries
No callbacks yet — scroll the stage to trigger one.

Every line here is one real IntersectionObserverEntry. Notice how few there are compared to how many pixels you scrolled — the callback only runs when visibility actually crosses your threshold, off the main scroll path.

4 What's running