Page transitions kill INP when animation or script work runs during interaction and pushes Interaction to Next Paint past the 200ms threshold. Safe transitions stay compositor-friendly, never block the next click or key press, and degrade to an instant navigation when motion is reduced. This guide covers the risk patterns, safer alternatives, and a preload strategy that helps without stalling input—practical rules we apply on every motion web development build.
INP is measured from interaction (click, tap, key) to the next time the browser paints a useful response. A transition that feels smooth in a demo can still hide long tasks on the main thread, deferred input handlers, or layout work that delays the paint your user is waiting for.
How transitions trigger INP
Core Web Vitals sets INP at “good” ≤200ms (with LCP ≤2.5s and CLS ≤0.1 as the neighboring thresholds you already manage). Transitions threaten INP in three common ways.
First, exit animations delay navigation: the user activates a link, the handler waits for a 400ms leave animation, and the browser never gets to paint the next view inside the interaction window. Second, heavy JavaScript sequences—measuring DOM, forcing reflow, orchestrating many elements per frame—put long tasks between the event and the paint. Third, input is implicitly deferred: listeners attached after the transition completes mean early clicks and keystrokes sit in a queue while the animation runs.
None of these require huge visual ambition. Even a modest crossfade becomes a problem if it gates the navigation task. The pattern choice matters more than the easing curve.
Transition patterns by INP risk
| Pattern | INP risk | What goes wrong | Safer approach |
|---|---|---|---|
| Delayed navigation waiting on exit animation | High | Click-to-next-view waits for the full leave sequence | Start navigation immediately; animate view layers independently of the route swap |
| Full-screen wipe driven by main-thread JS | High | Long tasks per frame; layout thrash on large surfaces | Compositor-only transforms/opacity; keep the wipe short and interruptible |
| View Transitions API where supported | Medium | Default handling can still stall if paired with heavy JS work | Use progressive enhancement; ensure an instant fallback path |
| Shared-element transition on every link | Medium | Snapshot and measure cost scales with page complexity | Reserve for hero/featured elements; instant swap elsewhere |
| Hover menus and in-page panels | Medium | Rapid pointer moves queue events; open/close work per event | Debounce intent, animate transform only, keep hit targets stable |
| CSS crossfade with transform/opacity | Low | Usually compositor-friendly if duration is short | Cap duration, avoid animating layout properties, honor reduced motion |
| Route preload on intent (hover/focus) | Low–Medium | Over-preloading can compete for bandwidth, not usually main thread | Preload likely next routes; do not preload everything on every page |
Patterns that stay safe
Decouple animation from navigation. The most reliable fix: never make the route change wait for the timeline. Either navigate first and animate the incoming view, or run a short overlay that does not block history updates and input. The user should be able to click again mid-transition without waiting for your sequence to finish.
Animate transform and opacity. Layout properties force style and layout work on the main thread. Translate, scale, rotate, and opacity can often run on the compositor, keeping frames cheap when the thread is busy with real work.
Keep sequences short and interruptible. A 150–250ms crossfade behaves better than a multi-second cinematic that swallows input. Spend any longer brand moment on the destination view’s entrance rather than a long exit that delays usefulness.
Do not gate listeners behind animation end. Attach handlers so clicks and keys work during the transition. Input that queues behind your own choreography is an avoidable self-inflicted INP hit.
Provide the reduced-motion path first-class. Under prefers-reduced-motion: reduce, transitions should collapse to an instant swap. That branch is both accessibility (WCAG 2.3.3) and a performance safety valve—implementation details are in prefers-reduced-motion: a practical guide.
Preload without blocking
Preloading helps when it removes a late discovery stall without competing with the interaction itself. Practical rules we use:
- Preload or prefetch the most likely next route from real intent signals—hover on a primary nav link, focus from keyboard, or pointerdown—not every anchor on the page.
- Warm critical assets for the current view first (hero image, main font files already in use). Do not let a transition’s assets crowd out LCP work on first load; LCP still has its own 2.5s budget.
- Load transition code as an enhancement. If the small script for crossfades arrives late, navigation must still work with zero animation.
- Avoid preloading large media for views the user may never open. Bandwidth spent is latency added to the views they will open—including the one being painted after their click.
Preload is a scalpel. Used broadly, it turns into cache noise; used narrowly around primary flows, it removes the “blank beat” users notice when a transition finishes but the next page is still empty.
What must never block input
Regardless of pattern, keep these off the critical interaction path: synchronous analytics flushes on click, scroll-jacking, heavy filter work in the same task as the click handler, and modals that animate open before attaching their close control.
Measure with the browser’s performance panel on a mid-range device profile. Watch for long tasks after click and any handler that runs after a timed animation rather than immediately. Fix by shortening, moving work off the main thread, or removing the decorative dependency entirely.
If you are choosing a motion system for a whole site rather than a single transition, sequence the decision through GSAP vs CSS and the structure in GSAP motion systems in production so transitions are budgeted as part of the system—not bolted on after launch.
Key takeaways
- INP’s good threshold is 200ms: transitions that delay navigation, run long main-thread tasks, or defer input handlers will push you over it. Animate transform/opacity, keep sequences short, and never make the route wait on decoration.
- Preload only what intent supports, ship motion as progressive enhancement, and collapse transitions under reduced motion. When in doubt, remove the wait between click and useful paint—spectacle does not matter if interaction feels broken.
FAQ
What INP threshold should we target for transition-heavy pages?
Good is INP ≤200ms as defined by the Core Web Vitals thresholds. Design transitions so the path from click to painted response stays well inside that budget on real devices—leaving headroom for your application’s own handlers, not only the animation.
Are CSS transitions safer than JavaScript for page transitions?
Often, yes, because short transform/opacity transitions can run without heavy main-thread orchestration. JavaScript becomes risky when it measures DOM per frame, forces layout, or delays navigation until the timeline completes. Either stack can be safe or unsafe depending on when navigation runs relative to the animation.
Should we use the View Transitions API?
It can simplify shared-element and cross-document effects where supported, but treat it as progressive enhancement and still provide an instant path. Pairing it with large synchronous work in the same transition re-creates the INP problems you were trying to avoid.
Does reduced motion help performance?
Yes as a side effect: collapsing transitions to near-zero duration removes animation work for users who opted out. The primary reason to implement it is accessibility under WCAG 2.3.3; the performance benefit is a welcome secondary gain on already-heavy sequences.
How do we test transitions against INP?
Use field data when you have enough real interactions, and lab profiling while building: record performance during representative clicks through the transition, look for long tasks between input and paint, and repeat on throttled CPU. Also test with reduced motion enabled to confirm the instant path never regresses into a hidden animation.