Blog

Scroll-Driven Animations: animation-timeline Instead of IntersectionObserver

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.

View Transitions in Next.js: Page Animations Without an Animation Library

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.

Core Web Vitals: What INP Really Measures, and How scheduler.yield() Saves the Main Thread

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.

Optimistic UI in React: An Interface That Knowingly Lies

The 'Like' button responds instantly, the heart fills in, the counter goes up – before the server has even answered. This isn't the speed illusion from the microinteractions article, it's something further-reaching: the interface shows a state that doesn't exist yet and assumes it's about to. I look at how to build this safely – with a real way to back out of the lie when the assumption doesn't hold – and why a manual setState-plus-catch is a worse version of what useOptimistic gives you for free.

Animated Microinteractions in Ecommerce

Two stores, the same product, the same server response time – yet one feels faster and more trustworthy. The difference comes down to microinteractions: a few hundred milliseconds of animation that decide whether a user trusts what's on screen. I break them down from first principles – the trigger/feedback model, what actually happens inside the browser's rendering engine, and prefers-reduced-motion.