The View Transitions API is routinely described as having gone cross-browser, and that description is half right in a way that matters. The API has two levels with very different support stories, and conflating them is how projects end up shipping a navigation experience that silently does nothing for a large share of visitors.

Here is the actual split as it stands.

Same-Document: Done

Level 1 — transitions within a single document, driven by document.startViewTransition() — is supported across all major engines and has been Baseline Newly Available since 14 October 2025, with Widely Available projected for April 2028. Chrome shipped it in 111 (March 2023) and Safari in 18 (September 2024); Firefox 144 closed the gap on the day the feature crossed into Baseline.

For single-page applications, tab panels, filtered lists, and any state change you own in JavaScript, this is settled. The progressive-enhancement guard is still worth keeping, because it costs one line:

const changeColor = () => {
  if (!document.startViewTransition) {
    updateColour();
    return;
  }
  document.startViewTransition(() => updateColour());
};

Cross-Document: Not Done

Level 2 — transitions across a real navigation between two documents — is a different feature with a different support table. Chrome and Edge shipped it in 126; Safari followed in 18.2. Firefox has not shipped it in a stable release, and view transition types are unimplemented there as well. (Some write-ups claim Firefox has view transitions entirely behind a flag as of mid-2026 — that is stale. Same-document transitions have been in stable Firefox since 144. It is specifically the cross-document half that is missing.)

MDN’s own status line for @view-transition is unambiguous: Limited availability, explicitly not Baseline, “because it does not work in some of the most widely-used browsers.”

That is worth stating plainly, because a number of 2026 write-ups assert the opposite. If your plan depends on cross-document transitions being universally available, the plan is built on a claim the compatibility data does not support. Build it as an enhancement that a third of your audience may not see, or use a client-side router that fakes the navigation and gets you Level 1 semantics everywhere.

:active-view-transition Is Baseline

The pseudo-class, unlike the at-rule, is settled: :active-view-transition became Baseline Newly Available on 13 January 2026, with Widely Available projected for July 2028. Chrome has had it since 125 and Safari since 18.2 — both back in 2024 — so Firefox 147 is what closed the gap. It is also part of Interop 2026.

It matches the root element only, while any view transition is in progress, and stops matching the moment the transition completes. That constraint is the whole design — it gives you a document-wide “a transition is happening right now” flag to hang descendant selectors off:

h2 {
  display: none;
}

:root:active-view-transition h2 {
  display: block;
}

:root:active-view-transition button {
  visibility: hidden;
}

This solves a real problem. Elements that shouldn’t be interactive or visible mid-animation — sticky toolbars, focus rings, tooltips, anything that reads as an artifact while the snapshot cross-fades — can be suppressed declaratively instead of through class toggling in the transition callback.

The functional sibling :active-view-transition-type() narrows the match to transitions carrying specific types, which is how you branch styling between a forward and a backward navigation. Note the Firefox caveat above: types are part of what isn’t implemented there.

For the same signal in JavaScript, Document.activeViewTransition holds the current transition object or null.

The Gotchas That Actually Bite

Assuming you are targeting cross-document transitions where they exist, several behaviors are non-obvious enough to cost an afternoon each.

Both pages must opt in. The rule is @view-transition { navigation: auto; }, and it has to be present in the CSS of the outgoing and incoming document. One side alone produces nothing. The old <meta> tag approach is deprecated and no longer functional.

Only same-origin, user-initiated navigations. Cross-origin links, programmatic redirects, and form submissions all skip the transition. Back and forward button navigations do fire it, which is easy to forget when you have only ever tested by clicking links.

There is a four-second timeout. If the incoming document doesn’t reach a state the browser considers renderable within four seconds of navigation start, the transition dies without warning. Slow TTFB, render-blocking resources, and a heavy critical path all draw down that budget. A transition that works locally and vanishes in production is usually this.

Images stretch by default. The old and new snapshots are sized independently of their aspect ratios, so a bitmap changing dimensions across the navigation distorts. The fix is explicit:

::view-transition-old(hero),
::view-transition-new(hero) {
  object-fit: cover;
}

Lifecycle events fire on every navigation. pageswap runs on the outgoing document, pagereveal on the incoming one — but both fire whether or not a transition is happening, so the viewTransition property on the event can be null. Guard it before touching it:

window.addEventListener('pagereveal', async (e) => {
  if (!e.viewTransition) return;        // ordinary navigation, no transition
  const from = new URL(navigation.activation.from.url);
  if (from.pathname.startsWith('/gallery/')) {
    e.viewTransition.types.add('from-gallery');
  }
  await e.viewTransition.ready;
});

The types set is what :active-view-transition-type() reads, so this is where a forward/backward or section-specific transition gets its label. It is also the code path Firefox will not execute, which is the practical shape of the support gap: the navigation still works, the styling branch simply never activates.

A Defensible Position for Now

Use same-document transitions freely; that level is finished. Use :root:active-view-transition to suppress mid-transition artifacts — it is Baseline and it replaces a genuinely awkward class-toggling pattern.

Treat cross-document transitions as an enhancement with a real support gap, keep both pages’ opt-in in place, and watch the four-second budget as a performance requirement rather than an animation detail. The API is good, and the same-document half is ready. Describing the whole thing as cross-browser is the part to stop repeating.