CSS Portal

::view-transition-new() CSS Pseudo Element

If this site has been useful, we’d love your support! Consider buying us a coffee to keep things going strong!

Description

The ::view-transition-new() pseudo-element represents the incoming (new) visual state of an element during a View Transition. It is part of the View Transitions API and is used to style how an element appears after a DOM update, while the transition animation is running. This pseudo-element exists only during the transition lifecycle and allows developers to animate, mask, fade, or transform the newly rendered content independently from the old content.

When a view transition is triggered - typically via JavaScript using document.startViewTransition() - the browser captures two visual snapshots: the “old” view and the “new” view. The new snapshot is exposed through ::view-transition-new(). This allows you to animate how the updated UI enters the screen, such as fading in new content, sliding elements into place, or applying clip-path effects. Unlike traditional animations that manipulate live DOM elements, this pseudo-element operates on a rendered snapshot, ensuring smooth and flicker-free transitions even during expensive DOM updates.

The ::view-transition-new() pseudo-element is most commonly paired with ::view-transition-old(), which represents the outgoing visual state. Together, they allow you to choreograph seamless transitions between page states. You can target them globally or per named transition using view-transition-name. This makes it ideal for page navigations, tab switches, filtering interfaces, or UI state changes where visual continuity matters.

Basic Example

Below is a simple example that fades in the new view while fading out the old one.

::view-transition-old(root) {
  animation: fade-out 300ms ease forwards;
}

::view-transition-new(root) {
  animation: fade-in 300ms ease forwards;
}

@keyframes fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

This example targets the root transition, meaning the entire page participates in the animation. The use of root refers to the document root rather than a specific element.

Targeting Specific Elements

You can apply view transitions to specific elements by assigning them a view-transition-name:

.card {
  view-transition-name: card;
}

::view-transition-new(card) {
  transform: translateY(10px);
  opacity: 0;
  animation: slide-in 250ms ease-out forwards;
}

@keyframes slide-in {
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

This approach allows only elements with the matching transition name to animate, which is useful for UI components like cards, modals, or navigation panels.

Interaction with Other Features

The ::view-transition-new() pseudo-element works well with modern layout and animation techniques, including transforms and opacity. Properties such as transform and opacity are especially effective because they are GPU-accelerated and do not trigger layout recalculations.

You can also combine view transitions with semantic HTML structures like main or section to create intuitive page-level animations that enhance navigation clarity without overwhelming the user.

Practical Use Cases

Common use cases for ::view-transition-new() include:

  • Smooth page transitions in multi-view web apps
  • Animated filtering or sorting of content
  • Soft transitions between tabs or panels
  • Enhancing perceived performance during DOM updates

Because the animation operates on a snapshot, it avoids layout thrashing and produces consistently smooth results, even on complex pages.

Syntax

::view-transition-new([ <pt-name-selector> <pt-class-selector>? ] | <pt-class-selector>) {
  /* ... */
}

Values

  • <pt-name-selector>This matches a specific view-transition-name defined in your CSS. For example, if you have header { view-transition-name: main-header; }, you would target it with ::view-transition-new(main-header).

Example

<div class="container">
<div id="box" class="box state-a"></div>
</div>

<button onclick="toggleTransition()">Toggle State</button>

<script>
function toggleTransition() {
const box = document.getElementById('box');

// Check for browser support
if (!document.startViewTransition) {
box.classList.toggle('state-b');
return;
}

// Start the transition
document.startViewTransition(() => {
box.classList.toggle('state-b');
});
}
</script>
/* 1. Define the element to be tracked */
.box {
view-transition-name: hero-box;
width: 100px;
height: 100px;
}

.state-a {
background-color: #3498db;
border-radius: 0%;
}

.state-b {
background-color: #e74c3c;
border-radius: 50%;
transform: translateX(200px);
}

/* 2. Style the "New" snapshot */
/* This targets the incoming state of the box */
::view-transition-new(hero-box) {
animation: 0.5s ease-in custom-fade-in;
outline: 4px solid gold; /* Adding a highlight to see it in action */
}

/* 3. Custom animation for the new snapshot */
@keyframes custom-fade-in {
from {
opacity: 0;
filter: blur(10px);
}
to {
opacity: 1;
filter: blur(0);
}
}

Browser Support

The following information will show you the current browser support for the CSS ::view-transition-new() pseudo element. Hover over a browser icon to see the version that first introduced support for this CSS psuedo element.

This psuedo element is supported by all modern browsers.
Desktop
Chrome
Edge
Firefox
Opera
Safari
Tablets & Mobile
Chrome Android
Firefox Android
Opera Android
Safari iOS
Samsung Internet
Android WebView
-

Last updated by CSSPortal on: 31st December 2025

If this site has been useful, we’d love your support! Consider buying us a coffee to keep things going strong!