Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      CodeSOD: A Unique Way to Primary Key

      July 22, 2025

      BrowserStack launches Figma plugin for detecting accessibility issues in design phase

      July 22, 2025

      Parasoft brings agentic AI to service virtualization in latest release

      July 22, 2025

      Node.js vs. Python for Backend: 7 Reasons C-Level Leaders Choose Node.js Talent

      July 21, 2025

      The best CRM software with email marketing in 2025: Expert tested and reviewed

      July 22, 2025

      This multi-port car charger can power 4 gadgets at once – and it’s surprisingly cheap

      July 22, 2025

      I’m a wearables editor and here are the 7 Pixel Watch 4 rumors I’m most curious about

      July 22, 2025

      8 ways I quickly leveled up my Linux skills – and you can too

      July 22, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      The Intersection of Agile and Accessibility – A Series on Designing for Everyone

      July 22, 2025
      Recent

      The Intersection of Agile and Accessibility – A Series on Designing for Everyone

      July 22, 2025

      Zero Trust & Cybersecurity Mesh: Your Org’s Survival Guide

      July 22, 2025

      Execute Ping Commands and Get Back Structured Data in PHP

      July 22, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      A Tomb Raider composer has been jailed — His legacy overshadowed by $75k+ in loan fraud

      July 22, 2025
      Recent

      A Tomb Raider composer has been jailed — His legacy overshadowed by $75k+ in loan fraud

      July 22, 2025

      “I don’t think I changed his mind” — NVIDIA CEO comments on H20 AI GPU sales resuming in China following a meeting with President Trump

      July 22, 2025

      Galaxy Z Fold 7 review: Six years later — Samsung finally cracks the foldable code

      July 22, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»How to Use the View Transition API for Better Web Transitions

    How to Use the View Transition API for Better Web Transitions

    July 1, 2025

    If you want to add some amazing and visually appealing animations to your web page, the View Transition API is a great animation tool. It lets you create Cross-Document Transitions when navigating between pages. And not just in classic multi-page apps – you can also use it to build eye-catching transitions in single-page applications.

    In this article, you’ll learn how to:

    • Enable cross-document transitions with a single line of CSS

    • Animate individual elements like titles and images

    • Debug and fine-tune your transitions

    • Apply the same API to dynamic interactions in single-page apps using JavaScript

    • Get an idea of how this works in a React or Next.js environment.

    Here’s what we’ll cover:

    • Prerequisites

    • Example Setup

    • Enabling Cross-Document Transitions

      • Debug Transition

      • First View Transition

      • Understanding View Transition Internals

      • Animating Images Across Pages

      • Endless Animation Opportunities

    • Single-Page Experience

      • Set Up the Event Listener

      • The Actual addStoryCard() Function

      • Applying the Animation

    • View Transition in React.js

    • View Transition in Next.js

    • Browser Support

    • Wrap-Up

    • Summary

    Prerequisites

    To follow along and get the most out of this guide, you should have:

    1. Basic HTML and CSS: You should understand how to structure a web page using HTML and apply styles using CSS.

    2. JavaScript fundamentals: Familiarity with JavaScript DOM manipulation, event handling, and basic functions will help you follow along with the dynamic examples.

    3. Modern browser environment: The View Transition API is currently supported in Chromium-based browsers like Chrome and Edge. Make sure you’re using a compatible browser.

    4. React and Next.js basics (optional): Toward the end of the article, we explore how to integrate view transitions in React and Next.js. Basic knowledge of component structure and routing in these frameworks will be helpful, though not strictly required for the core concepts.

    If you’re new to any of these topics, you can still follow along and revisit the article later with hands-on practice.

    I’ve also created a video to go along with this article. If you’re the type who likes to learn from video as well as text, you can check it out here:

    Example Setup

    For your demo, you have two simple HTML pages – from.html and to.html – that share the same stylesheet (style.css). from.html page displays a grid of story cards. When you click a card on the first page, its image enlarges and moves to the to.html page.

    View Transition Demo

    <!-- from.html -->
    <link rel="stylesheet" href="style.css">
    
    <div class="stories-container">
        <div class="story-card">
            <img
                src="./assets/image-3.jpg"
                alt="World in the Glass"
                id="story-image"
            />
            <a href="./to.html">
                <div class="story-overlay">
                    <div class="story-content">
                        <div class="story-tag" id="story-tag">
                            Sci-Fi
                        </div>
                        <h2 class="story-title">World in the Glass</h2>
                        <p class="story-description">
                            A cyberpunk adventure in a dystopian future
                            where reality and virtual worlds collide.
                        </p>
                    </div>
                </div>
            </a>
        </div>
        <!-- more story cards… -->
    </div>
    
    <!-- to.html -->
    <link rel="stylesheet" href="style.css">
    
    <section class="story-hero">
        <img id="hero-image" src="./assets/image-3.jpg" />
        <div class="story-hero-overlay" id="overlay">
            <div class="breadcrumb" id="breadcrumb">
                <a href="from.html">My Stories</a>
                <span class="breadcrumb-separator">/</span>
                <a href="#">World in the Glass</a>
            </div>
            <div class="story-tag" id="story-tag">Sci-Fi</div>
            <h1 class="story-title">World in the Glass</h1>
            <div class="story-meta" id="story-meta">
                <div class="story-meta-item">
                    <span>Created: June 1, 2025</span>
                </div>
                <!-- additional markup… -->
            </div>
        </div>
    </section>
    
    <section class="story-content-wrapper">
        <div class="story-content">
            <div class="story-main">
                <div class="story-chapter">
                    <h2 class="chapter-title" id="title">
                        Chapter 1: The Discovery
                    </h2>
                    <!-- additional markup… -->
                </div>
            </div>
        </div>
    </section>
    

    Instead of showing the full HTML markup here, I’ve only included the key snippet to help you understand the idea. You’ll find the complete code in the GitHub repository at the end of the article.

    You’ll see that most of our work happens in style.css, because although the View Transition API is a JavaScript API, you control it heavily with CSS.

    Enabling Cross-Document Transitions

    To turn on cross-document transitions, add just one line to your CSS:

    @view-transition {
        navigation: auto;
    }
    

    Now, when you navigate between two pages – even using the browser’s “Back” and “Forward” buttons – you’ll see a smooth cross-fade by default.

    Debug Transition

    If the animation feels too fast, you can use the Developer Tools in Google Chrome browser to slow it down. This not only helps you follow the animation more clearly, but also gives you a chance to learn how to debug animations using Chrome’s DevTools. Just follow the steps below:

    • Open DevTools in your Chrome Browser

    • Click the three dot icon on top right corner (you can follow the diagram below)

    • Click “More Tools” → Animations

    Debugging Animation with Chrome DevTools

    • Then slow the animation speed (for example to 10%) so you can watch it in detail.

    Animation Speed Control with DevTools

    First View Transition

    By default, the entire document cross-fades, which is quite boring. To animate a specific element – like the “page title” – give it a view-transition-name:

    #title {
        view-transition-name: title;
    }
    

    Both pages use the same id="title", so the API knows to treat them as one element. Now, when you click a card, the title gracefully moves from its position on the first page to its spot on the detail page – forward and backward. Just with these three lines of code, you get a pretty decent morph transition! Isn’t it interesting?

    Understanding View Transition Internals

    To see how the API works under the hood:

    1. Open DevTools and pause the animation.

    2. Navigate between pages. You’ll notice a new overlay in the Elements panel. This overlay is made up with the CSS pseudo-element ::view-transition

      Discovering ::view-transition

    3. Inside, you’ll find two Pseudo-element groups:

      • ::view-transition-group-root (the default cross-fade)

      • ::view-transition-group-title (for the named element title)

        View Transition Pseudo-element groups

    You can target these groups in CSS. For example, to control all transitions’ duration:

    ::view-transition-group(*) {
        animation-duration: 0.5s;
    }
    

    Or to disable the root default cross-fade while keeping your title animation:

    ::view-transition-group(root) {
        animation: none;
    }
    

    Animating Images Across Pages

    Let’s animate the story image from the gallery into the larger hero image on the detail page. Here, the IDs differ – #story-image on from.html and #hero-image on to.html – so you select both and name the transition picture:

    #story-image,
    #hero-image {
        view-transition-name: picture;
    }
    

    Default Animation

    By default, you’ll see two cross-fading snapshots (“old” and “new”). But this animation isn’t perfect for us. To understand this you’ll go a bit deeper. Open DevTools again and pause the animation. Then, click on the story card in the from.html page. Now, you can scrub the playhead back and forth in the Animations panel to understand the problem and fine-tune the overlap.

    Finding the default animation overlap problem

    Digging Into the Problem to Understand It Better

    Just by looking at it, you can already see the problem. While the animation is playing, the state of the from.html page (you can think of this state as the snapshot of the old state) overlaps with the incoming state or snapshot of the to.html page. They blend into each other in a way that doesn’t look good visually. You can check the snapshots of the old and new state of the transitions in the elements panel in the DevTools.

    Overlapping issue identified

    There, you’ll notice a new pseudo-element group ::view-transition-group(picture). If you expand it, another group appears: ::view-transition-image-pair(picture).

    Inside that, you’ll find two more pseudo-elements: ::view-transition-old(picture) and ::view-transition-new(picture). The naming is pretty self-explanatory. The “image pair” reflects my earlier analogy of treating the before-and-after states as snapshots – you have one for the old state and one for the new. Makes sense now?

    Improving the Animation

    Now that you understand the concept and have identified the issue, let’s adjust the CSS to improve the animation. You noticed that the new snapshot appears on top of the old one. The old snapshot covers the full height of the parent element ::view-transition-image-pair(picture), while the new one is smaller. They’re cross-fading over each other, which doesn’t look great.

    To fix this, you can target both the “old” and “new” snapshots and set their height to 100%. Since the default cross-fade feels a bit dull, you’ll also disable the built-in animation and set their mix-blend-mode property to normal so they don’t visually overlap in an odd way. Finally, you’ll make sure both snapshots have the same border-radius so the transition between the two looks smooth and consistent.

    ::view-transition-old(picture),
    ::view-transition-new(picture) {
        animation: none;
        mix-blend-mode: normal;
        height: 100%;
        border-radius: 0 0 30px 30px;
    }
    

    Digging Deeper to Discover Hidden Issues

    Now, if you repeat the debugging process and take a closer look, you’ll see that the overlapping issue is resolved. But there’s still one problem: the ::view-transition-new(picture) element on top appears distorted. You can fix this by setting its object-fit property to cover and hiding any overflow. This will ensure the image scales properly without stretching and stays neatly within its container.

    #to::view-transition-new(picture) {
        object-fit: cover;
        overflow: hidden;
    }
    

    Here, I’ve specifically targeted the ::view-transition-new(picture) pseudo-element of the to page using the #to identifier – because I added unique IDs to the elements of both from.html and to.html.

    <!-- from.html -->
    <html lang="en" id="from">
        <!-- code goes here -->
    </html>
    
    <!-- to.html -->
    <html lang="en" id="to">
        <!-- code goes here -->
    </html>
    

    Now, if you check the animation closely, you’ll notice that the transition from from.html to to.html looks perfect.

    Next, let’s handle the “back” navigation – transitioning from to.html back to from.html. If you debug this reverse transition, you’ll see that the old snapshot ::view-transition-new(picture) appears completely distorted during the animation.

    Back navigation distortion issue

    To fix this, you can target the new snapshot on the from page and set its object-fit to cover.

    #from::view-transition-new(picture) {
        object-fit: contain;
    }
    

    Now, if you debug and inspect again, the distortion is gone! But if you carefully follow the animation, you’ll notice another issue – the lower snapshot (which is ::view-transition-old(picture) on the from.html page) – is overlapping awkwardly, as illustrated in the diagram below:

    New snapshot overlapping the old one

    To fix this final piece, you can target the ::view-transition-old(picture) pseudo-element on the from page. Then you apply object-fit: cover, hide any overflow, and match the border-radius to 20px – just like the destination snapshot – for a smooth and visually consistent transition.

    #from::view-transition-old(picture) {
        object-fit: cover;
        overflow: hidden;
        border-radius: 20px;
    }
    

    Further Fine-Tuning for Perfection

    After making these changes, the picture animation finally feels perfect! As you can see, the View Transition API is both simple and powerful. All it really takes is targeting the right pseudo-elements and applying the CSS skills you already have to fine-tune the transition.

    It might feel a bit tedious at first – but that’s the nature of animation work, whether it’s in web development or video editing.

    These small, detailed adjustments are what make your animations smoother and your user experience truly delightful. The more you debug, the more opportunities you uncover for improvement. So let’s dive a bit deeper and see if there’s anything else you can refine.

    If you pause the animation and navigate from the from.html page to the to.html page, you’ll notice that the snapshot of the incoming page title overlaps with the old one – as shown in the diagram below.

    Page title overlap issue

    You can solve this easily. When your titles overlap during the transition, hide the old title at the right moment:

    ::view-transition-old(title) {
        opacity: 0;
    }
    

    Now, if you check again, you’ll see that the title no longer overlaps – and the animation is finally looking perfect!

    Endless Animation Opportunities

    The View Transition API isn’t limited to just targeting pseudo-elements or relying on default animations. You can bring in all your CSS animation and transition skills to craft stunning, eye-catching custom animations. Let’s look at one more example to get a better sense of what’s possible.

    Finding the Opportunity

    When you transition from the from.html page to the to.html page, the image animates smoothly. But there’s an issue: a darker overlay suddenly appears on top of the image, along with the text content inside it. Both the overlay and the text pop in abruptly, which doesn’t look great. So let’s fix that.

    If you inspect the elements in DevTools, you’ll see I’ve intentionally given the overlay an ID of #overlay. All the text content on the to.html page lives inside this element.

    Ideally, when you transition from from.html to to.html, the overlay should also appear with a smooth animation. Notice that the from.html page doesn’t have this overlay at all. Up to this point, everything you’ve done has involved transitioning between elements that exist on both pages – elements that have counterparts. But in this case, you want to transition from “nothing” to “something.” And yes, that’s also possible with the View Transition API.

    Implement the Idea

    Without saying anything else, let’s go ahead and target the #overlay element first and assign it a custom transition name “overlay”. This gives us the flexibility to control its animation separately from the rest of the elements.

    #overlay {
        view-transition-name: overlay;
    }
    

    Now that you’ve set this up, let’s see what’s actually happening. If you pause the animation and debug it, just like before, you’ll notice a new pseudo-element ::view-transition-group(overlay). Inside this group, within the image pair, you’ll find only ::view-transition-new(overlay) – there’s no ::view-transition-old(overlay).

    Why is that? It’s simple: on the previous page (from.html), there is no element with the ID overlay. Since there’s nothing to take a snapshot of, the browser doesn’t create a ::view-transition-old(overlay).

    Likewise, when navigating back from to.html to from.html, there will only be a ::view-transition-old(overlay) – and no ::view-transition-new(overlay) – because the overlay exists only on the page you’re leaving.

    What you want to do now is animate this element in a nice way. Since you’re transitioning from “nothing” to “something”, you can define a custom CSS animation. A simple and elegant effect could be a fade-in from the bottom.

    Defining Custom Keyframes

    To achieve that, you can define a custom keyframe animation called fade-in. In this animation, you’ll start from opacity: 0 and position the element slightly lower – for example, translateY(50px) – and then animate it upwards as it fades in.

    @keyframes fade-in {
        from {
            opacity: 0;
            transform: translateY(50px);
        }
    }
    

    For the reverse (fading out) you can simply transition the opacity back to 0.

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

    Using the Keyframe Animations

    Now that you’ve defined our keyframe animations, you can target the ::view-transition-new(overlay) element and apply the fade-in animation to it. You’ll also add a slight animation delay – let’s say 0.5 seconds. This delay ensures that our custom animation begins after the default cross-fade animation has completed. Since you previously set a 0.5 second delay for the transition, this timing helps everything flow smoothly, without overlapping animations.

    ::view-transition-new(overlay) {
        animation: 250ms cubic-bezier(0, 0, 0.3, 1) both fade-in;
        animation-delay: 0.5s;
    }
    

    And in the case of the “old” state (meaning when you navigate back), you simply target the ::view-transition-old(overlay) element and apply the fade-out animation to it.

    ::view-transition-old(overlay) {
        animation: 50ms cubic-bezier(0.3, 0, 1, 1) both fade-out;
    }
    

    Fine-Tuning for Perfection

    Now let’s pause for a moment and check if any fine-tuning is needed. This step is essential when working with View Transitions, which is why I keep emphasizing it.

    If you look closely during the fade-in and fade-out animations, you’ll notice an overflow issue: a subtle black area briefly appears underneath the overlay.

    Black overlay underneath issue

    To fix this, you can simply select the entire ::view-transition-group(overlay) and hide its overflow. That should take care of the issue immediately.

    ::view-transition-group(overlay) {
        overflow: hidden;
    }
    

    Now, if you check again, you’ll see that the animation looks perfect!

    Single-Page Experience

    Up until now, you’ve explored how the View Transition API works in the context of cross-document or multi-page applications – something that wasn’t natively possible before.

    But now, let’s shift our focus to Single Page Applications (SPAs). In most SPAs, animations have always been part of the experience, even before the View Transition API was introduced. Developers have long used various JavaScript tricks to create smooth transitions within SPAs. But with the View Transition API, you can now implement these transitions natively and much more easily. Let’s quickly take a look at how that works.

    Let’s talk about the interaction we’re focusing on. When you click the “New Story” button, a new story card should appear. Then, we are going to animate this interaction using the View Transition API.

    But first, let me quickly show you how this works under the hood. It’s a simple DOM (Document Object Model) operation. I’ve specifically targeted the button and added an event listener to its onclick event. So what does that listener do? It creates a new card element and injects it directly into the DOM. Let’s break down how this code creates a new story card using JavaScript.

    Set Up the Event Listener

    You can set up the Event Listener in five simple steps:

    Step 1: Select the Button

    You’ll begin by selecting the button that the user will click to create a new story card. This line uses document.querySelector() to grab the first element on the page with the class name .new-story-btn and stores it in the newStoryButton variable.

    const newStoryButton = document.querySelector(".new-story-btn");
    

    Step 2: Set up the Click Event Listener

    Next, add a click event listener to that button. This means that when the user clicks the “New Story” button, the function you define inside this event listener will run. The function is marked async in case you later want to use await inside it – for example, if you fetch data or run animations that need to wait.

    newStoryButton.addEventListener("click", async () => {
        // you will write the listener code here
    });
    

    Step 3: Select the Container for Story Cards

    Now that the button has been clicked, you grab the container where our story cards are displayed. This is the element with the class .stories-container, and it’s where you’ll append the new card in the next steps.

    // select the container for story cards
    const container = document.querySelector(".stories-container");
    

    Step 4: Create a new Story Card

    You’ll call a helper function named addStoryCard() – presumably a custom function that returns a ready-made DOM element representing a story card. We pass it the story details: tag, title, description, and an image path. This function likely handles the creation of the HTML structure, styling, and maybe even animations for the card.

    const newCard = addStoryCard({
        tag: "Fantasy",
        title: "Sky Kingdoms",
        description:
            "A tale of floating islands and the heroes who defend them.",
        image: "./assets/image-5.jpg",
    });
    

    Step 5: Add the Card to the Page

    Finally, the newly created card is appended to the .stories-container, making it visible on the page. At this point, the user will see the “Sky Kingdoms” story card appear in the list of stories.

    container.appendChild(newCard);
    

    That’s it. Here’s the full event listener function:

    newStoryButton.addEventListener("click", async () => {
        const container = document.querySelector(".stories-container");
    
        const newCard = addStoryCard({
            tag: "Fantasy",
            title: "Sky Kingdoms",
            description:
                "A tale of floating islands and the heroes who defend them.",
            image: "./assets/image-5.jpg",
        });
    
        container.appendChild(newCard);
    });
    

    The Actual addStoryCard() Function

    Let’s take a closer look at the helper function addStoryCard(), which is responsible for generating a brand-new story card using some predefined structure and inserting custom content into it.

    Step 1: Find the Template Card

    You begin by selecting the existing .story-card element from the DOM. This element acts as your template – a ready-made design that you can clone to create new cards. You also add a simple safety check: if for some reason the template doesn’t exist on the page, the function exits immediately by returning undefined.

    function addStoryCard(data) {
        const templateCard = document.querySelector(".story-card");
        if (!templateCard) return;
    }
    

    Step 2: Clone the Template

    Once you have the template, you’ll create a deep clone of it using cloneNode(true). This means it copies the element and all of its nested child elements – preserving the full structure of the card. At this point, you have a fresh new card element in memory that looks just like the original.

    const newCard = templateCard.cloneNode(true);
    

    Step 3: Update the Image (if any)

    If an image is provided in the data object, you find the img tag inside the new card and update its img attribute.

    if (data.image) {
        const currentImage = newCard.querySelector("img");
        currentImage.setAttribute("img", `url('${data.image}')`);
    }
    

    Step 4: Update the Text Content

    Now you customize the card’s text:

    • You look for the .story-tag, .story-title, and .story-description elements inside the card.

    • If they exist, you set their text content based on the data object that was passed in. This is where the story gets its actual content – like the tag (“Fantasy”), title (“Sky Kingdoms”), and description.

    const tag = newCard.querySelector(".story-tag");
    const title = newCard.querySelector(".story-title");
    const desc = newCard.querySelector(".story-description");
    if (tag) tag.textContent = data.tag;
    if (title) title.textContent = data.title;
    if (desc) desc.textContent = data.description;
    

    Step 5: Return the Final Card

    Finally, you return the fully prepared story card so it can be added to the page wherever needed.

    return newCard;
    

    So here’s the full addStoryCard function:

    function addStoryCard(data) {
        const templateCard = document.querySelector(".story-card");
        if (!templateCard) return;
    
        // Clone the card
        const newCard = templateCard.cloneNode(true);
    
        // Update image if provided
        if (data.image) {
            const currentImage = newCard.querySelector("img");
            currentImage.setAttribute("img", `url('${data.image}')`);
        }
    
        // Update content
        const tag = newCard.querySelector(".story-tag");
        const title = newCard.querySelector(".story-title");
        const desc = newCard.querySelector(".story-description");
        if (tag) tag.textContent = data.tag;
        if (title) title.textContent = data.title;
        if (desc) desc.textContent = data.description;
    
        return newCard;
    }
    

    Now, if you click on the “New Story” button, a new story card appears dynamically – thanks to the simple DOM operations you’ve already written above. But you can make it more engaging. Instead of the card just popping into place, you want to add a smooth, eye-catching transition when it’s added to the container.

    Can you do this with plain CSS? Unfortunately, no – because the card is being added dynamically via JavaScript, CSS alone won’t catch this change and animate it. That’s where the View Transition API in JavaScript comes in. With just a bit of extra code, you can bring this interaction to life with a smooth and polished transition effect.

    Applying the Animation

    In your event listener function, after creating the card DOM node, you just appended it to the container using the below code:

    container.appendChild(newCard);
    

    This line – container.appendChild(newCard) – is the core operation you want to animate.

    So how do you make this transition happen smoothly? You can’t use CSS alone here, because the new element is being inserted dynamically using JavaScript. But that’s not a problem, as JavaScript gives you full control over DOM manipulation, including the ability to apply styles on the fly.

    To enable the View Transition API for your newCard, you simply need to assign a viewTransitionName to it. You can do this by setting the style.viewTransitionName property on the newCard element. You’ll give the transition a name targeted-card, just like you did in the CSS-based example earlier.

    newCard.style.viewTransitionName = "targeted-card";
    

    This tells the browser: “Track this element during the transition and animate it.” And with that single line, your dynamically added element becomes part of a smooth, native-feeling UI animation.

    And now you can start the transition using the View Transition JavaScript API like below:

    const transition = document.startViewTransition(async () => {
        container.appendChild(newCard);
    });
    

    Here, you use the startViewTransition() method provided by the browser. This is a modern API that helps you animate changes between two visual states of the page – before and after the DOM updates. Inside startViewTransition(), you pass an asynchronous callback function, in this case:

    () => {
        container.appendChild(newCard);
    }
    

    This is the DOM change you want to animate: adding the newCard into the .stories-container. Normally, adding a new DOM element would just appear instantly on the page. But with this API, you’re telling the browser:

    Hey, I’m about to change the DOM. Please capture the visual state before the change, apply my DOM update, then animate the transition between the old and new state.

    Now you need to pause here and wait until the animation is fully complete as this is an asynchronous task. You can do this like below:

    await transition.finished;
    

    Now that the animation is finished, you remove that name by setting it to null. This step is important to avoid unintended animations if the card is later updated or moved again. Think of it as cleaning up after the animation is done.

    newCard.style.viewTransitionName = null;
    

    So here’s the full code all in one go, combining everything we just discussed.

    // name the transition
    newCard.style.viewTransitionName = "targeted-card";
    
    // start the transition
    const transition = document.startViewTransition(async () => {
        container.appendChild(newCard);
    });
    
    // wait for the transition to finish
    await transition.finished;
    
    // finally cleanup the transition when finished
    newCard.style.viewTransitionName = null;
    

    Now, if you reload the page and try it out, you’ll see a smooth, beautiful transition when a new card is created. It’s a subtle touch, but it makes the interaction feel much more polished and dynamic.

    And that’s how you can harness the power of JavaScript to add any animation you want – just like you did with CSS, but by setting style properties dynamically. The possibilities are endless when you combine your CSS skills with the flexibility of JavaScript and the View Transition API.

    View Transition in SPA

    View Transition in React.js

    If you are a React Developer, you can play with the experimental <ViewTransition> React component to play with this API.

    import {unstable_ViewTransition as ViewTransition} from 'react';
    
    <ViewTransition>
      <div>...</div>
    </ViewTransition>
    

    Please note that this API is experimental and is not available in a stable version of React yet. You can try it by upgrading React packages to the most recent experimental version.

    • react@experimental

    • react-dom@experimental

    • eslint-plugin-react-hooks@experimental

    You can check details from the React.js official Documentation.

    View Transition in Next.js

    If you are a Next.js Developer, just like vanilla React, you can try the View Transition API

    To enable this feature, you need to set the viewTransition property to true in your next.config.js file.

    /** @type {import('next').NextConfig} */
    const nextConfig = {
      experimental: {
        viewTransition: true,
      },
    }
    
    module.exports = nextConfig
    

    Please note that viewTransition is an experimental flag that enables the new experimental View Transitions API in React. Please check details from the Next.js official Documentation.

    Browser Support

    Browser Support varies (Firefox doesn’t yet support it), so be sure to review the compatibility table before shipping to production.

    Wrap-Up

    The View Transition API lets you:

    • Enable cross-document transitions with one line of CSS

    • Animate individual elements by naming them

    • Debug transitions in DevTools and fine-tune timing and easing

    • Apply the same approach to single-page apps using JavaScript

    For more details, check out the MDN documentation on View Transitions. Enjoy creating seamless, native animations in your web projects!

    You can find all the source code from this guide in this GitHub repository. If it helped you in any way, consider giving it a star to show your support!

    Also, if you found the guide valuable, feel free to share it with others who might benefit from it. I’d really appreciate your thoughts – mention me on X @sumit_analyzen, watch my coding tutorials, or simply connect with me on LinkedIn.

    Source: freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleHow to Fetch API Data in React Using Axios
    Next Article Beginner’s Guide to Cloud Cybersecurity

    Related Posts

    Development

    GPT-5 is Coming: Revolutionizing Software Testing

    July 22, 2025
    Development

    Win the Accessibility Game: Combining AI with Human Judgment

    July 22, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    “We are not tied to a console release.” We got Hollow Knight: Silksong release date news after all, but it had nothing to do with Xbox Ally

    News & Updates

    Perfection is a Myth. Leverage Isn’t: How Small Teams Can Secure Their Google Workspace

    Development

    CodeSOD: A Jammed Up Session

    News & Updates

    Simplify your accounting, GST invoicing, and inventory management with GSTMate – your all-in-one desktop GST solution from Apptrop.

    Web Development

    Highlights

    Key Factors to Consider Before Hiring React Native Developers for Your Project🔍

    April 22, 2025

    Post Content Source: Read More 

    Fortinet Patches CVE-2025-32756 Zero-Day RCE Flaw Exploited in FortiVoice Systems

    May 14, 2025

    What they’re not teaching in design class

    June 13, 2025

    CVE-2025-39205 – “MicroSCADA X SYS600 IEC 61850 TLS Certificate Validation Vulnerability”

    June 24, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.