The Symptom
Symptom
Root Cause Analysis
Root Cause
The matrix was a massive 100x100 grid of financial data (10,000 DOM nodes). The developers used a deeply nested `display: grid` structure where columns were set to `auto` or `min-content`. Furthermore, a React `onScroll` listener was attempting to calculate the `getBoundingClientRect()` of the container to implement a sticky header. This combination caused "Layout Thrashing" (Forced Synchronous Layout).
5 Whys Root Cause Drill-Down
Every time the user scrolled 1 pixel, the `onScroll` event fired. The JS asked the browser for the element's exact height. The browser had to pause JS, calculate the height of all 10,000 dynamically sized grid cells, return the value, and then resume JS. Doing this 60 times a second instantly killed the browser.
// The fatal flaw: Reading layout properties synchronously during paint events
window.addEventListener("scroll", () => {
// Forces a massive synchronous layout calculation
const rect = gridRef.current.getBoundingClientRect();
if (rect.top < 0) setSticky(true);
});
Resolution
Resolution
// The fix: Asynchronous Intersection Observer
const observer = new IntersectionObserver(([entry]) => {
setSticky(!entry.isIntersecting);
});
observer.observe(headerRef.current);
Discussions 0