For years, animated transitions between pages were a feat of engineering. Either you adopted an SPA framework (Next.js, Nuxt, Astro with built-in view transitions), or you patched things together with JavaScript libraries that intercepted navigation and redrew the DOM by hand. On WordPress, most integrators simply gave up: too many plugins, too much risk of breakage, too little return on investment.
The View Transitions API changes that. Standardised by the W3C, it lets the browser itself handle visual transitions between two states of a page — and now between two distinct pages. As of April 2026, it is supported across all three major engines: Blink (Chrome 111+, Edge 111+), WebKit (Safari 18+) and Gecko (Firefox 133+) for the same-document mode, with cross-document mode rolling out quickly after its arrival in Chrome 126.
For a WordPress site, this opens up a pragmatic path: adding elegant transitions without rewriting the theme in JavaScript, without a heavy plugin, and without degrading Core Web Vitals.
Two modes: same-document and cross-document
The API distinguishes two scenarios. The same-document mode (often called SPA) operates within a single page: you modify the DOM, and document.startViewTransition() captures the before and after states to interpolate them. This is the original version, the one modern single-page applications rely on.
The cross-document mode (MPA) covers classic navigation: you click a link, the browser loads a new page, and the transition unfolds between the two documents. No JavaScript required; everything happens through a CSS @view-transition rule. This mode is precisely what makes the API interesting for WordPress, where navigation remains fundamentally multi-page.
The base rule is concise:
@view-transition {
navigation: auto;
}
Placed in the main stylesheet, it is enough to enable a default cross-fade transition between all same-origin pages. The visitor clicks an article, the browser loads it, and then reveals the new page with a soft fade rather than an abrupt jump.
Enabling the View Transitions API on a WordPress theme
In practice, integration happens at the child theme level. In style.css or a dedicated stylesheet registered via wp_enqueue_style, you add the rule above. The prerequisite is that pages share the same origin (which is the WordPress default) and that the visitor's browser supports the API. For others, degradation is graceful: no transition, no error, no warning.
To go beyond the simple fade, you customise the pseudo-elements generated by the API. During a transition, the browser creates a tree accessible from CSS: ::view-transition, ::view-transition-group(*), ::view-transition-image-pair(*), ::view-transition-old(*) and ::view-transition-new(*). Each can be animated independently.
A common example on a WordPress blog is sliding the main content out to the left while the new article slides in from the right.
@view-transition {
navigation: auto;
}
::view-transition-old(root) {
animation: 250ms ease-in both slide-out-left;
}
::view-transition-new(root) {
animation: 300ms ease-out both slide-in-right;
}
@keyframes slide-out-left {
to { transform: translateX(-30px); opacity: 0; }
}
@keyframes slide-in-right {
from { transform: translateX(30px); opacity: 0; }
}
The effect is subtle but perceived as fluid by users, without taxing the browser.
Animating a specific element between two pages
The most appealing aspect of the API reveals itself when you name an element with view-transition-name. Take the typical case of a post grid: the thumbnail of the clicked article should grow and become the featured image of the next page. On WordPress, this is the scenario of a blog with article cards opening on the full permalink.
On the listing side (for example archive.php or home.php), assign a unique name to each featured image:
<?php while ( have_posts() ) : the_post(); ?>
<article class="post-card">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail( 'medium', [
'style' => 'view-transition-name: post-' . get_the_ID() . ';'
] ); ?>
<h2><?php the_title(); ?></h2>
</a>
</article>
<?php endwhile; ?>
On the article side (single.php), the featured image carries the same name:
<?php
the_post_thumbnail( 'large', [
'style' => 'view-transition-name: post-' . get_the_ID() . ';'
] );
?>
The browser recognises that this is the same logical element and orchestrates a smooth morph animation between the two positions and sizes. No library, no manual calculation: the native presentation layer handles it.
The caching and plugin trap on WordPress
This is where WordPress slightly complicates things. Several caching or optimisation plugins (WP Rocket, Autoptimize, LiteSpeed Cache) inject their own pre-loading or instant-navigation scripts. Some, like WP Rocket's Instant Page feature, intercept clicks and load the next page in the background. Without precaution, their logic conflicts with the native triggering of view transitions.
The practical rule: always test with and without cache, and disable JavaScript pre-loading if you notice stutters. Conversely, HTTP pre-loading (rel=prefetch, Speculation Rules) remains compatible and even improves the perception of speed during the transition.
Polylang, which powers itamde.com, poses no issue at all. Since cross-document transitions only work within the same origin, switching between language versions automatically benefits from the animation, with no extra configuration.
Accessibility: respecting prefers-reduced-motion
A point too often overlooked in online demos. Animated transitions can cause discomfort for people sensitive to motion, and WCAG 2.1 AA requires honouring the system prefers-reduced-motion preference. With the View Transitions API, that's immediate:
@media (prefers-reduced-motion: reduce) {
::view-transition-old(*),
::view-transition-new(*) {
animation: none !important;
}
}
You disable animations for users who request it, without breaking navigation. Content appears instantly, just as on a classic site.
What's the impact on Core Web Vitals?
A legitimate question, especially after Google's early-2026 adjustments that strengthened the weight of INP (Interaction to Next Paint). The View Transitions API runs through the browser's compositor layer, off the main thread. In practice, a well-built transition raises neither LCP nor INP in any measurable way.
Two traps remain, however. First, multiplying view-transition-name declarations on dozens of elements per page creates GPU overhead on lower-end devices — target only meaningful elements (featured images, main headings), not the entire page. Second, animations that run too long (beyond 400 ms) delay the perceived arrival on the new page and frustrate the user. The comfortable range sits between 200 and 350 ms.
What this changes in our projects
For a studio like ours, the View Transitions API removes a technical decision that often used to be painful: should we leave WordPress for a headless stack to deliver modern transitions? The answer, in 2026, is no. A classic, well-maintained WordPress theme can now offer a visual experience close to that of a native application, with no extra JavaScript dependency.
The integration effort fits in a few dozen lines of CSS. User feedback is immediate, especially on mobile where the jump between two pages remains the main perceived disruption. And since degradation is silent, there is no risk for visitors on older browsers.
One constraint remains: cross-document mode is not yet universal. For a site whose audience is mostly European on recent Chrome, Edge and Safari, coverage is already largely sufficient. For a broader project, you combine native view transitions on supporting browsers with a simple fallback elsewhere — which the API already handles on its own.







0 Comments