EngineTransitions+ Browser Compatibility
EngineTransitions+ treats page animation as progressive enhancement. Navigation and state updates must remain functional even when a browser does not expose the native View Transitions API.
Runtime tiers
v2.6.2 uses three compatibility tiers:
native View Transitions available
→ native captured-page transition + NE preset animation
no native View Transitions, Web Animations available
→ short NE root fade around the update/navigation
no compatible animation API
→ normal update/navigation with no animationThis means an NE link is never allowed to become unusable merely because a browser is older than the transition effect.
Current major browsers
Modern Chromium-family browsers, Firefox, and Safari/WebKit builds with same-document View Transitions use the full native Transitions+ path.
Chromium-family includes browsers such as Chrome, Edge, Brave, and current Opera builds. Safari/WebKit and Firefox use their own implementations rather than Chromium's.
The browser matrix in CI exercises:
Chromium
Firefox
WebKitThe WebKit project is the closest automated proxy for current Safari behavior available on Linux CI.
Older browser behavior
A browser can be supported by a Next.js application while still being too old for native View Transitions. v2.6.2 no longer turns that into an all-or-nothing transition feature.
When document.startViewTransition is unavailable, NE uses Web Animations for a small root fade and still waits for the actual Next.js update/navigation. If Web Animations is also unavailable, the update runs immediately.
No polyfill is required.
Firefox and older-engine CSS compatibility
Transitions+ no longer emits typed multiplication expressions such as:
calc(-1 * 10deg)
calc(-.35 * 36px)
calc(.5 * 7px)Those calculations are unnecessary because NE already owns the numeric preset values. v2.6.2 performs the arithmetic in JavaScript and emits ordinary values:
-10deg
-12.6px
3.5pxThis applies to the more complex liquid, depth, flip, page-turn, scatter, rgb, and portal preset frames.
Shared element names
Shared transitions use DOM ids, but a DOM id is not copied directly into view-transition-name.
v2.6.2 creates a readable sanitized prefix plus a deterministic hash of the original id:
raw DOM id
→ readable safe prefix
→ deterministic id hash
→ unique view-transition-nameThis prevents names such as Foo Bar and foo-bar, or two very long ids with the same truncated prefix, from collapsing to the same transition name.
Animation fallback safety
If a browser exposes View Transitions but rejects one of NE's requested pseudo-element animations, NE now follows this fallback order:
requested preset frames
↓ failure
safe fade frames
↓ failure
skip custom transition animation
↓
finish the update/navigationA transition effect is never more important than completing the route change.
Same-URL navigation
Animated push() / replace() calls now normalize the destination URL before starting the navigation wait.
If the requested URL is already the current URL, NE lets the router handle it immediately rather than waiting for a URL mutation that can never occur.
Concurrent native transitions
The browser exposes one active same-document View Transition. EngineTransitions+ therefore routes both preset transitions and app-level coordinateEngineViewTransition() calls through a shared coordinator.
App-level theme/class/attribute changes use conflict: "skip" by default. If a route transition is already active, the update still runs but its additional native animation is skipped. NE navigation uses conflict: "replace", preserving the existing latest-action-wins behavior.
The coordinator attaches handlers to all three native lifecycle promises (ready, updateCallbackDone, and finished) as soon as a transition starts. The AbortError produced when a visual transition is superseded is a normal "cancelled" result. Errors thrown by the update callback are not swallowed and still reject the coordinator call.
Reduced motion
prefers-reduced-motion: reduce remains a hard animation bypass for Transitions+. The actual update/navigation still occurs.
Automated compatibility coverage
tests/browser/engine-compat.spec.ts runs through Playwright on Chromium, Firefox, and WebKit. The suite checks:
- real SSR/client hydration of generated Engine styles;
- an initially-open EngineDialog;
- a complex
liquidstate transition; - animated route navigation;
- same-URL transition completion;
- a coordinated theme update immediately followed by animated navigation;
- the fallback path with native View Transitions disabled;
- reduced-motion behavior;
- browser page errors and hydration-related console errors.
The lighter scripts/engine-transitions-compat-smoke.js additionally rejects typed CSS multiplication and checks collision-safe shared names without needing a browser download. scripts/engine-view-transition-coordinator-smoke.js deterministically proves replacement cancellation, app-level conflict skipping, fallback updates, callback error propagation, and the absence of unhandled native promise rejections.
Compatibility principle
NE does not require every supported browser to render every visual effect identically.
The contract is:
- the page and route must work;
- accessibility preferences must be respected;
- modern browsers receive the richest safe effect they support;
- older engines degrade to a simpler animation or normal navigation;
- compatibility fallback must never require disabling SSR or turning the Engine into a client-only framework.