Six cards on a dashboard, six spinners, and they don't appear together — they appear one after another, like dominoes, because each one only started fetching after the one above it finished. That's a waterfall, and the total wait isn't the slowest request, it's the sum of all of them. use() and Suspense break the chain, but the interesting part is the machinery underneath: what a suspended component actually throws, and how HTML that arrives out of order still lands in the right place.
There's a reason JavaScript parallax always looks slightly wrong — a little detached, like the layers are swimming half a frame behind the page. It isn't sloppy code. It's that scroll events reach your JavaScript after the browser has already painted the scroll. The browser solved this once before, when it turned sticky headers into position: sticky. Scroll-driven animations are the same move, applied to every scroll-linked effect at once.
For ten years, animating a thumbnail into a hero image meant one technique: measure the element before, measure it after, fake the difference with a transform, and let it play. FLIP. Every animation library does it, and every one of them pays for it with JavaScript on the main thread at the worst possible moment. The View Transitions API moves that whole trick into the browser — and since React 19.2 and Next.js 16, the entire contract is a single prop called name.
In the article on microinteractions I wrote that transform and opacity animate on the compositor thread, so even a heavy page shouldn't cause a button animation to stutter. That's still true — with one caveat that article left out: if the main thread is blocked by a long JS task, the animation may never get a chance to start, because the click handler itself is stuck in a queue. INP is the metric that measures exactly this gap — and scheduler.yield() is one of the few ways to actually close it.
A list of a thousand comments renders slowly, so you reach for react-window – and in exchange for smooth scrolling you lose Ctrl+F, page printing, and part of screen-reader navigation, because elements outside the window stop physically existing in the DOM. content-visibility solves the same problem differently: elements stay in the DOM, the browser simply skips the expensive layout and paint work for them until they're near the visible area – and, surprisingly, it can temporarily reveal them when you search for text inside.
In the accessibility article, a modal built with display:none that still lingered in the accessibility tree was an example of a mistake that comes from building a modal from scratch out of divs. The real question is: why did it have to be built from scratch at all? I look at what native <dialog> and the popover attribute give you for free – top layer, focus trapping, light dismiss – and where these two mechanisms differ just enough that mixing them up is a quick path to an inaccessible interface.