When building a micro-frontend app, I ran into a deceptively simple requirement: after a user triggers an external redirect (OAuth, payment flow, etc.) and returns to the page, scroll back to the element they were interacting with.
My first instinct was "just save the position and scroll back." That turned out to be wrong.
The real insight: this is a timing problem, not a scroll problem. Three things must happen in sequence, each at the correct moment in the browser's rendering pipeline. Once I mapped this out, every technical decision fell into place.
Part 1: The Map — Browser Event Loop
Before any solution, let's build the map. One iteration of the browser event loop runs in four phases:
MutationObserver's callback fires after appendChild but before the next paint — the earliest possible moment to detect the new node. setInterval can't guarantee landing in this precise window.
Important: at this point, the node exists in the DOM but has not been painted yet. Those are two different things, and the gap between them is exactly what Step 3 handles.
Step 3: Wait for the Element to Be Painted
This is the easiest step to get wrong.
Whether you find the element in useEffect directly (fast path) or via MutationObserver (slow path), at the moment of discovery the element is in the DOM but not yet painted. Calling scrollIntoView immediately forces the browser to synchronously compute Layout before it's finished — a forced reflow. The result is inconsistent and potentially inaccurate positioning.
The candidates for "wait until painted":
SOCIAL SHARE CARD GENERATOR