[ad_1]
Remaining time we met, I presented you to the View Transitions API. We began with a easy default crossfade transition and implemented it to other use instances involving features on a web page transitioning between two states. A kind of examples took the fundamental concept of including merchandise to a buying groceries cart on an e-commerce website and developing a visible transition that signifies an merchandise added to the cart.
The View Transitions API continues to be regarded as an experimental function that’s lately supported simplest in Chrome on the time I’m scripting this, however I’m offering that demo underneath in addition to a video in case your browser is not able to fortify the API.
See the Pen [Add to cart animation v2 – completed [forked]](https://codepen.io/smashingmag/pen/GReJGYV) by means of Adrian Bece.
That used to be a amusing instance! The concept that we will successfully take “snapshots” of a component’s sooner than and after states and generate a transition between them the use of cyber web requirements is fantastic.
However do you know that we will do even extra than transition features at the web page? In reality, we will transition between two complete pages. The similar deal applies to single-page packages (SPA): we will transition between two complete perspectives. The result’s an revel in that feels so much like an put in cell app and the web page transitions which have been unique to them for a while.
That’s precisely what we’re going to hide in the second one part of this two-part sequence. If you wish to assessment the primary section, please do! For those who’re in a position to plow forward, then come and practice alongside.
A Fast Overview
The browser does a large number of heavy lifting with the View Transitions API, permitting us to create complicated state-based UI and web page transitions in a extra streamlined approach. The API takes a screenshot of the “previous” web page, plays the DOM replace, and when the replace is whole, the “new” web page is captured.
It’s necessary to show that what we see all the way through the transition is changed content material in CSS, simply the similar as different features, together with pictures, movies, and iframes. That suggests they don’t seem to be in fact DOM features, and that’s necessary as it avoids doable accessibility and usefulness problems all the way through the transition.
const transition = report.startViewTransition(() => {
/* Take screenshot of an outgoing state */
/* Replace the DOM - transfer the thing from one container to some other */
vacation spot.appendChild(card);
/* Seize the are living state and carry out a crossfade */
});
With this little little bit of JavaScript, we will name the report.startViewTransition
operate, and we get the View Transition API’s default animation that plays a crossfading transition between the outgoing and incoming detail states.
What we wish to do, even though, is inform the View Transitions API to take note of positive UI features at the web page and look ahead to their role and dimensions. That is the place the CSS view-transition-name
assets is available in. We practice the valuables to a unmarried detail at the web page whilst the transition operate is operating; transition names will have to be distinctive and implemented as soon as in keeping with web page — bring to mind them like an identity
characteristic in HTML.
That being stated, we will practice distinctive view transition names to a couple of features all the way through the transition. Let’s choose one detail in the intervening time — we’ll name it .active-element
— and provides it a view transition call:
.active-item {
view-transition-name: active-item;
}
Shall we do that in JavaScript as an alternative:
activeItem.taste.viewTransitionName = "active-item";
Once we make a decision to set the transition call, the detail itself turns into what’s referred to as a transition detail between the outgoing and incoming state alternate. Different features nonetheless obtain the crossfade animation between outgoing and incoming states.
From right here, we will use CSS to customise the animation. In particular, we get an entire new set of pseudo-elements we will use to focus on and choose positive portions of the transition. Let’s say we have now a “card” part that we’ve recognized and given a transition call. We will outline a suite of CSS @keyframes
, set it at the two states (::view-transition-image-pair(card-active)
), then configure the animation at other ranges, reminiscent of making use of a definite animation timing operate, postpone, or period to all the transition organization (::view-transition-group(*)
), the “previous” web page (::view-transition-old(root)
), or the “new” web page (::view-transition-new(root)
).
/* Extend final card motion */
::view-transition-group(*) {
animation-timing-function: ease-in-out;
animation-delay: 0.1s;
animation-duration: 0.2s;
}
/* Extend container shrinking (shrink after playing cards have moved) */
::view-transition-old(root),
::view-transition-new(root) {
animation-delay: 0.2s;
animation-duration: 0s; /* Steer clear of crossfade animation, resize immediately */
}
/* Observe customized keyframe animation to previous and new state */
::view-transition-image-pair(card-active) {
animation: popIn 0.5s cubic-bezier(0.7, 2.2, 0.5, 2.2);
}
/* Animation keyframes */
@keyframes popIn { /* ... */ }
Understand how we’re deciding on positive UI features in each and every pseudo-element, together with all the transition organization with the common selector (*
), the root
of the previous and new states, and the card-active
we used to call the watched detail.
Ahead of we plow forward, it’s value yet one more reminder that we’re running with an experimental cyber web function. The most recent variations of Chrome, Edge, Opera, and Android Browser lately fortify the API. Safari has taken a favorable role on it, and there’s an open price tag for Firefox adoption. We need to look forward to those ultimate two browsers to officially fortify the API sooner than the use of it in a manufacturing setting.
And although we have now Chromium fortify, that’s were given a little bit of nuance to it as simplest Chrome Canary helps multi-page view transitions these days at the back of the view-transition-on-navigation
flag. You’ll be able to paste the next into the Chrome Canary URL bar to get entry to it:
chrome://flags/#view-transition-on-navigation
Complete View Transitions For Multi-Web page Programs
Let’s get started with multi-page packages (MPA). The examples are more uncomplicated than they’re for SPAs, however we will leverage what we know about MPAs to assist perceive view transitions in SPAs. In particular, we’re going to construct a static website with the Eleventy framework and create other transitions between the website’s other pages.
Once more, MPA view transitions are simplest supported in Chrome Canary view-transition-on-navigation
flag. So, in case you’re following alongside, be sure to’re the use of Chrome Canary with the function flag enabled. Both approach, I’ll come with movies of what we’re making to assist display the ideas, like this one we’re about to take on:
That appears beautiful tough! However we’re beginning with the baseline default crossfade animation for this transition and can take issues one step at a time to look how the entirety provides up.
Beginning With The Markup
I need to show off vanilla JavaScript and CSS implementations of the API so that you could use it on your personal tech stack with no need to re-configure a number of stuff. Even In case you are unfamiliar with Eleventy, don’t fear as a result of I’ll use the compiled HTML and CSS code within the examples so you’ll be able to practice alongside.
Let’s take a look at the HTML for a .card
detail. As soon as Eleventy generates HTML from the template with the information from our Markdown information, we get the next HTML markup.
!-- Merchandise grid detail at the record web page (homepage) -->
<a href="https://smashingmagazine.com/some-path" magnificence="card">
<determine magnificence="card__figure">
<image>
<!-- Choose AVIF pictures -->
<supply sort="picture/avif" srcset="https://smashingmagazine.com/2024/01/view-transitions-api-ui-animations-part2/...">
<!-- JPG or PNG fallback -->
<img magnificence="card__image" src="https://smashingmagazine.com/2024/01/view-transitions-api-ui-animations-part2/..." width="600" top="600">
</image>
<figcaption magnificence="card__content">
<h2 magnificence="card__title">Reign Of The Reaper</h2>
<h3 magnificence="card__subtitle">Sorcerer</h3>
</figcaption>
</determine>
</a>
So, what we’re running with is a hyperlink with a .card
magnificence wrapped round a <determine>
that, in flip, incorporates the <img>
in a <image>
that has the <figcaption>
as a sibling that still incorporates its personal stuff, together with <h2>
and <h3>
features. When clicking the .card
, we can transition between the present web page and the .card
’s corresponding hyperlink.
Crossfading Transitions
Enforcing crossfade transitions in MPAs is in fact a one-line snippet. In reality, it’s a <meta>
tag that we will drop proper into the report <head>
along different meta data.
<meta call="view-transition" content material="same-origin" />
We will nonetheless use the report.startViewTransition
operate to create on-page UI transitions like we did within the examples from the former article. For crossfade web page transitions, we simplest wish to practice this HTML meta
tag, and the browser handles the remaining for us!
Bear in mind, then again, that that is what’s lately simplest supported in Chrome Canary. The true implementation may well be modified between now and formal adoption. However for now, that is all we wish to get the easy crossfade web page transitions.
I’ve to show how tricky it will be to put in force this with out the View Transitions API. It’s superb to look those app-like web page transitions between same old HTML paperwork that run natively within the browser. We’re running at once with the platform!
Transitioning Between Two Pages
We’re going to proceed configuring our View Transition with CSS animations. Once more, it’s superior that we will hotel to the use of same old CSS @keyframes
relatively than some library.
First, let’s take a look at the venture pages and the way they’re connected in combination. A person is in a position to navigating from the homepage to the thing main points web page and again, in addition to navigating between two merchandise main points pages.

The ones diagrams illustrate (1) the beginning web page, (2) the vacation spot web page, (3) the kind of transition, and (4) the transition features. The next is a more in-depth have a look at the transition features, i.e., the weather that obtain the transition and are tracked by means of the API.

So, what we’re running with are two transition features: a header and a card part. We can configure the ones in combination one after the other.
The default crossfade transition between the pages has already been set, so let’s get started by means of registering the header as a transition detail by means of assigning it a view-transition-name
. First, let’s take a peek on the HTML:
<div magnificence="header__wrapper">
<!-- Hyperlink again arrow -->
<a category="header__link header__link--dynamic" href="https://smashingmagazine.com/">
<svg ...><!-- ... --></svg>
</a>
<!-- Web page identify -->
<h1 magnificence="header__title">
<a href="https://smashingmagazine.com/" magnificence="header__link-logo">
<span magnificence="header__logo--deco">Vinyl</span>Emporium </a>
</h1>
<!-- ... -->
</div>
When the person navigates between the homepage and an merchandise main points web page, the arrow within the header seems and disappears — relying on which route we’re transferring — whilst the identify strikes relatively to the proper. We will use show: none
to deal with the visibility.
/* Disguise again arrow at the homepage */
.house .header__link--dynamic {
show: none;
}
We’re in fact registering two transition features throughout the header: the arrow (.header__link--dynamic
) and the identify (.header__title
). We use the view-transition-name
assets on either one of them to outline the names we need to name the ones features within the transition:
@helps (view-transition-name: none) {
.header__link--dynamic {
view-transition-name: header-link;
}
.header__title {
view-transition-name: header-title;
}
}
Notice how we’re wrapping all of this in a CSS @helps
question so it’s scoped to browsers that in fact fortify the View Transitions API. Thus far, so excellent!
Card Transition Part
Turning our consideration to the cardboard part, it’s value recalling that all view transitions on a web page will have to have distinctive names. So, relatively than set the cardboard’s call up entrance in CSS, let’s as an alternative assign it to the cardboard as soon as the cardboard’s picture is clicked to assist keep away from doable conflicts.
There are other ways to assign a view-transition-name
to the clicked card. For instance, we will use mouse occasions. For this demo, then again, I’ve determined to make use of the Navigation API as it’s a excellent excuse to paintings with it and put its talent to observe again and ahead browser navigation to make use of. In particular, we will use it to intercept a navigation match and use a question selector at the card picture containing the matching goal href
that has been clicked directly to assign a reputation for the transitioning detail.
// Application operate for making use of view-transition-name to clicked detail
operate applyTag(url) {
// Choose a picture in a hyperlink matching the hyperlink that has been clicked on.
const picture = report.querySelector(
`a[href="https://smashingmagazine.com/2024/01/view-transitions-api-ui-animations-part2/${url.pathname}"] .card__image`
);
if (!picture) go back;
picture.taste.viewTransitionName = "product-image";
}
// Intercept the navigation match.
navigation.addEventListener("navigate", (match) => {
const toUrl = new URL(match.vacation spot.url);
// Go back if origins don't fit or if API isn't supported.
if (!report.startViewTransition || location.beginning !== toUrl.beginning) {
go back;
}
applyTag(toUrl);
});
The article main points web page is our vacation spot, and we will assign the view-transition-name
assets to it at once in CSS since it’s at all times going to be an identical picture.
<segment magnificence="product__media-wrapper" taste="--cover-background-color: #fe917d">
<nav magnificence="product__nav">
<span>
<a category="product__link product__link--prev" href="https://smashingmagazine.com/2024/01/view-transitions-api-ui-animations-part2/...">
<svg ... ><!-- ... --></svg>
</a>
</span>
<span>
<a category="product__link product__link--next" href="https://smashingmagazine.com/2024/01/view-transitions-api-ui-animations-part2/...">
<svg ... ><!-- ... --></svg>
</a>
</span>
</nav>
<article magnificence="product__media">
<div magnificence="product__image">
<!-- LP sleeve conceal picture -->
<image>
<supply sort="picture/avif" srcset="https://smashingmagazine.com/2024/01/view-transitions-api-ui-animations-part2/...">
<img src="https://smashingmagazine.com/2024/01/view-transitions-api-ui-animations-part2/..." width="600" top="600">
</image>
</div>
<div magnificence="product__image--deco">
<!-- LP picture -->
<image>
<supply sort="picture/avif" srcset="https://smashingmagazine.com/2024/01/view-transitions-api-ui-animations-part2/...">
<img src="https://smashingmagazine.com/2024/01/view-transitions-api-ui-animations-part2/..." width="600" top="600">
</image>
</div>
</article>
</segment>
We will additionally customise the animations we’ve simply created the use of same old CSS animation
homes. For now, let’s simply mess around with the animation’s period and easing operate.
@helps (view-transition-name: none) {
.product__image {
view-transition-name: product-image;
}
::view-transition-old(*),
::view-transition-new(*) {
animation-timing-function: ease-in-out;
animation-duration: 0.25s;
}
::view-transition-group(product-image) {
animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
animation-duration: 0.4s;
}
}
And identical to that, we have now created a neat web page transition! And all we truly did used to be assign a few transition features and modify their period and timing purposes to get the general end result.
Running With Extra Advanced Animations
Let’s transfer directly to further, extra complicated animations that run after the web page transition has completed. We gained’t in fact use them simply but, however we’re environment them up in order that we can use them for transitioning between two product main points pages.
Why are we going with the CSS animations, impulsively? For those who recall from the primary article on this two-part sequence, the web page isn’t interactive whilst the View Transitions API is operating. Even if the transition animations glance easy and lovely, we need to stay them as brief as conceivable so we don’t make the person look forward to too lengthy to have interaction with the web page. We additionally need as a way to interrupt the animation when the person clicks on a hyperlink.
The next CSS defines two units of animation @keyframes
: one for the album to open
up its conceal, and some other for the album itself to rollOut
of the sleeve.
/* LP gatefold sleeve open animation and types */
.product__media::sooner than {
/* Disguise till animatton starts (keep away from z-index problems) */
opacity: 0;
/* ... */
animation: open 0.25s 0.45s ease-out forwards;
}
/* LP roll out animation and types */
.product__image--deco {
/* Disguise till animatton starts (keep away from z-index problems) */
opacity: 0;
/* ... */
animation: rollOut 0.6s 0.45s ease-out forwards;
}
@keyframes open {
from {
opacity: 1;
change into: rotateZ(0);
}
to {
opacity: 1;
change into: rotateZ(-1.7deg);
}
}
@keyframes rollOut {
from {
opacity: 1;
change into: translateX(0) translateY(-50%) rotateZ(-45deg);
}
to {
opacity: 1;
change into: translateX(55%) translateY(-50%) rotateZ(18deg);
}
}
Test it out! Our CSS animations are actually integrated within the transitions.
We aren’t reasonably executed but. We haven’t in fact implemented the animations. Let’s do this sooner than enjoying with the animation somewhat extra.
Transitioning Between Two Pieces Connected To Other Pages
OK, so we’ve already finished an instance of a view transition between two pages in an MPA. We did it by means of connecting the website’s international navigation to any product main points web page when clicking both at the header hyperlink or the cardboard part.
We additionally simply created two CSS animations that we haven’t put to make use of. That’s what we’ll do subsequent to set a view transition when navigating between two product pages. For this one, we can create a transition at the product pictures by means of clicking at the left or proper arrows on each side of the product to view the former or subsequent product, respectively.

To do this, let’s get started by means of defining our transition features and assign transition names to the weather we’re transitioning between the product picture (.product__image--deco
) and the product disc at the back of the picture (.product__media::sooner than
).
@helps (view-transition-name: none) {
.product__image--deco {
view-transition-name: product-lp;
}
.product__media::sooner than {
view-transition-name: flap;
}
::view-transition-group(product-lp) {
animation-duration: 0.25s;
animation-timing-function: ease-in;
}
::view-transition-old(product-lp),
::view-transition-new(product-lp) {
/* Got rid of the crossfade animation */
mix-blend-mode: standard;
animation: none;
}
}
Understand how we had to take away the crossfade animation from the product picture’s previous (::view-transition-old(product-lp)
) and new (::view-transition-new(product-lp)
) states. So, for now, a minimum of, the album disc adjustments immediately the instant it’s situated again at the back of the album picture.
However doing this tousled the transition between our international header navigation and product main points pages. Navigating from the thing main points web page again to the homepage ends up in the album disc final visual till the view transition finishes relatively than operating once we want it to.
The way in which we repair that is by means of getting rid of transitions when returning to a prior state. Once we’re running with elaborate web page transitions like this one, we need to remember of the entire various kinds of navigation paths that may happen and make sure transitions run easily irrespective of which course a person takes or which route they navigate.
Identical to we will assign view-transition-name
attributes when wanted, we will additionally take away them to revive the detail’s default crossfade transition. Let’s as soon as once more use the Navigation API, this time to intercept the navigation match at the merchandise main points web page. If the person is navigating again to the homepage, we’ll merely set the view-transition-name
of the album disc detail to none
to stop conflicts.
operate removeTag() {
const picture = report.querySelector(`.product__image--deco`);
picture.taste.viewTransitionName = "none";
}
navigation.addEventListener("navigate", (match) => {
const toUrl = new URL(match.vacation spot.url);
if (!report.startViewTransition || location.beginning !== toUrl.beginning) {
go back;
}
// Take away view-transition-name from the LP if navigating to the homepage.
if (toUrl.pathname === "https://smashingmagazine.com/") {
removeTag();
}
});
Now, all our bases are lined, and we’ve controlled to create this reputedly complicated web page transition with quite little effort! The crossfade transition between pages works proper out of the field with a unmarried meta tag added to the report <head>
. All we do from there’s set transition names on features and mess around with CSS animation homes and @keyframes
to make changes.
Demo
The next demo comprises the code snippets which can be at once related to the View Transitions API and its implementation. In case you are concerned about your complete codebase or need to mess around with the instance, be at liberty to take a look at the supply code on this GitHub repository. Differently, a are living demo is to be had underneath:
Complete View Transitions For Unmarried-Web page Programs
The View Transition API will get somewhat tough in single-page packages (SPA). As soon as once more, we wish to depend at the report.startViewTransition
operate as a result of the entirety is treated and rendered with JavaScript. Thankfully, routing libraries exist, like react-router, and they’ve already applied web page transitions with the View Transitions API as an opt-in. Different libraries are following go well with.
On this subsequent educational, we’ll use react-router to create the transitions captured within the following video:
There are a couple of various kinds of transitions going down there, and we’re going to make they all. The ones come with:
- Transition between class pages;
- Transition between a class web page and a product main points web page;
- Transition the product picture on a product main points web page to a bigger view.
We’ll start by means of putting in place react-router sooner than tackling the primary transition between class pages.
React Router Setup
Let’s get started by means of putting in place our router and major web page elements. The elemental setup is that this: we have now a homepage that represents one product class, further pages for different classes, and pages for each and every particular person product.

Let’s configure the router to check that construction. Each and every course will get a loader
operate to deal with web page information.
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Class, { loader as categoryLoader } from "./pages/Class";
import Main points, { loader as detailsLoader } from "./pages/Main points";
import Format from "./elements/Format";
/* Different imports */
const router = createBrowserRouter([
{
/* Shared layout for all routes */
element: <Layout />,
children: [
{
/* Homepage is going to load a default (first) category */
path: "https://smashingmagazine.com/",
element: <Category />,
loader: categoryLoader,
},
{
/* Other categories */
path: "/:category",
element: <Category />,
loader: categoryLoader,
},
{
/* Item details page */
path: "/:category/product/:slug",
element: <Details />,
loader: detailsLoader,
},
],
},
]);
const root = ReactDOM.createRoot(report.getElementById("root"));
root.render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);
With this, we have now established the routing construction for the app:
- Homepage (
/
); - Class web page (
/:class
); - Product main points web page (
/:class/product/:slug
).
And relying on which course we’re on, the app renders a Format
part. That’s all we want so far as putting in place the routes that we’ll use to transition between perspectives. Now, we will get started running on our first transition: between two class pages.
Transition Between Class Pages
We’ll get started by means of enforcing the transition between class pages. The transition plays a crossfade animation between perspectives. The one a part of the UI that doesn’t take part within the transition is the ground border of the class filter out menu, which supplies a visible indication for the energetic class filter out and strikes between the previously energetic class filter out and the lately energetic class filter out that we can in the end sign in as a transition detail.

Since we’re the use of react-router, we get its web-based routing resolution, react-router-dom, baked proper in, giving us get entry to to the DOM bindings — or router elements we wish to stay the UI in sync with the present course in addition to an element for navigational hyperlinks. That’s additionally the place we achieve get entry to to the View Transitions API implementation.
In particular, we can use the part for navigation hyperlinks (Hyperlink
) with the unstable_viewTransition
prop that tells the react-router to run the View Transitions API when switching web page contents.
import { Hyperlink, useLocation } from "react-router-dom";
/* Different imports */
const NavLink = ({ slug, identify, identity }) => {
const { pathname } = useLocation();
/* Take a look at if the present nav hyperlink is energetic */
const isMatch = slug === "https://smashingmagazine.com/" ? pathname === "https://smashingmagazine.com/" : pathname.comprises(slug);
go back (
<li key={identity}>
<Hyperlink
className={isMatch ? "nav__link nav__link--current" : "nav__link"}
to={slug}
unstable_viewTransition
>
{identify}
</Hyperlink>
</li>
);
};
const Nav = () => {
go back
<nav className={"nav"}>
<ul className="nav__list">
{classes.pieces.map((merchandise) => (
<NavLink {...merchandise} />
))}
</ul>
</nav>
);
};
This is actually all we wish to sign in and run the default crossfading view transition! That’s once more as a result of react-router-dom is giving us get entry to to the View Transitions API and does the heavy lifting to summary the method of environment transitions on features and perspectives.
Growing The Transition Parts
We simplest have one UI detail that will get its personal transition and a reputation for it, and that’s the visible indicator for the actively decided on product class filter out within the app’s navigation. Whilst the app transitions between class perspectives, it runs some other transition at the energetic indicator that strikes its role from the beginning class to the vacation spot class.
I do know that I had previous described that visible indicator as a backside border, however we’re in fact going to ascertain it as a regular HTML horizontal rule (<hr>
) detail and conditionally render it relying at the recent course. So, principally, the <hr>
detail is totally got rid of from the DOM when a view transition is caused, and we re-render it within the DOM underneath no matter NavLink
part represents the present course.
We would like this transition simplest to run if the navigation is visual, so we’ll use the react-intersection-observer
helper to test if the detail is visual and, whether it is, assign it a viewTransitionName
in an inline taste.
import { useInView } from "react-intersection-observer";
/* Different imports */
const NavLink = ({ slug, identify, identity }) => {
const { pathname } = useLocation();
const isMatch = slug === "https://smashingmagazine.com/" ? pathname === "https://smashingmagazine.com/" : pathname.comprises(slug);
go back (
<li key={identity}>
<Hyperlink
ref={ref}
className={isMatch ? "nav__link nav__link--current" : "nav__link"}
to={slug}
unstable_viewTransition
>
{identify}
</Hyperlink>
{isMatch && (
<hr
taste={{
viewTransitionName: inView ? "marker" : "",
}}
className="nav__marker"
/>
)}
</li>
);
};
Transitioning Between Two Product Perspectives
Thus far, we’ve applied the default crossfade transition between class perspectives and registered the <hr>
detail we’re the use of to signify the present class view as a transition detail. Let’s proceed by means of setting up the transition between two product perspectives.
What we wish is to sign in the product view’s major picture detail as a transition detail each and every time the person navigates from one product to some other and for that transition detail to in fact transition between perspectives. There’s additionally a case the place customers can navigate from a product view to a class view that we wish to account for by means of falling again to a crossfade transition in that circumstance.

First, let’s check out our Card
part used within the class perspectives. As soon as once more, react-router-dom
makes our process quite simple, because of the unstable_useViewTransitionState
hook. The hook accepts a URL string and returns true
if there’s an energetic web page transition to the objective URL, in addition to if the transition is the use of the View Transitions API.
That’s how we’ll make certain that our energetic picture stays a transition detail when navigating between a class view and a product view.
import { Hyperlink, unstable_useViewTransitionState } from "react-router-dom"; /* Different imports */ const Card = ({ writer, class, slug, identity, identify }) => { /* We will use the similar URL price for the Hyperlink and the hook */ const url = `/${class}/product/${slug}`; /* Take a look at if the transition is operating for the thing main points pageURL */ const isTransitioning = unstable_useViewTransitionState(url); go back ( <li className="card">
<Hyperlink unstable_viewTransition to={url} className="card__link">
<determine className="card__figure">
<img
className="card__image"
taste=}}
/* Observe the viewTransitionName if the cardboard has been clicked on */
viewTransitionName: isTransitioning ? "item-image" : "",
}}
src={`/belongings/${class}/${identity}-min.jpg`}
alt=""
/>
{/* ... */}
</determine>
<div className="card__deco" />
</Hyperlink>
</li>
);
};
export default Card;
We all know which picture within the product view is the transition detail, so we will practice the viewTransitionName
at once to it relatively than having to wager:
import { Hyperlink, useLoaderData, unstable_useViewTransitionState, } from "react-router-dom"; /* Different imports */ const Main points = () => { const information = useLoaderData(); const { identity, class, identify, writer } = information; go back ( <> <segment className="merchandise"> {/* ... */} <article className="item__layout"> <div> <img
taste={{viewTransitionName: "item-image"}}
className="item__image"
src={`/belongings/${class}/${identity}-min.jpg`}
alt=""
/>
</div>
{/* ... */}
</article>
</segment>
</>
);
};
export default Main points;
We’re on a excellent observe however have two problems that we wish to take on sooner than transferring directly to the general transitions.
One is that the Card
part’s picture (.card__image
) incorporates some CSS that applies a set one-to-one element ratio and centering for keeping up constant dimensions it doesn’t matter what picture report is used. As soon as the person clicks at the Card
— the .card-image
in a class view — it turns into an .item-image
within the product view and must transition into its authentic state, devoid of the ones additional types.
/* Card part picture */
.card__image {
object-fit: conceal;
object-position: 50% 50%;
aspect-ratio: 1;
/* ... */
}
/* Product view picture */
.item__image {
/* No aspect-ratio implemented */
/* ... */
}
In different phrases, the transition detail is blind to the CSS this is liable for the ones types and is not able to trace it by itself. We wish to customise it with CSS pseudo-elements in the similar approach we did in the former article of this two-part sequence.
Jake Archibald shared this easy and efficient CSS snippet for dealing with the element ratio adjustments. We’re going to make use of it right here with some minor changes for our particular use case.
/* That is identical as within the Jake Archibald's snippet */
::view-transition-old(item-image),
::view-transition-new(item-image) {
/* Save you the default animation,
so each perspectives stay opacity:1 during the transition */
animation: none;
/* Use standard mixing,
so the brand new view sits on most sensible and obscures the previous view */
mix-blend-mode: standard;
/* Make the peak the similar as the crowd,
which means the view dimension may no longer fit its aspect-ratio. */
top: 100%;
/* Clip any overflow of the view */
overflow: clip;
}
/* Transition from merchandise main points web page to class web page */
.class::view-transition-old(item-image) {
object-fit: conceal;
}
.class::view-transition-new(item-image) {
object-fit: include;
}
/* Transition from class web page to merchandise main points web page */
.main points::view-transition-old(item-image) {
object-fit: include;
}
.main points::view-transition-new(item-image) {
object-fit: conceal;
}
Subsequent, we’ll use the unstable_useViewTransitionState
to conditionally set a viewTransitionName
at the picture simplest when the person navigates from the product view again to the class web page for that product.
import { Hyperlink, useLoaderData, unstable_useViewTransitionState, } from "react-router-dom"; /* Different imports */ const Main points = () => { const information = useLoaderData(); const { identity, class, identify, writer } = information;
const categoryUrl = `/${class}`;
const isTransitioning = unstable_useViewTransitionState(categoryUrl);
go back ( <> <segment className="merchandise"> { /* ... */ } <article className="item__layout"> <div> <img
taste={{
viewTransitionName: isTransitioning ? "item-image" : "",
}}
className="item__image"
src={`/belongings/${class}/${identity}-min.jpg`}
alt=""
/>
</div>
{/* ... */}
</article>
</segment>
</>
);
};
export default Main points;
Let’s stay this situation easy and center of attention only on methods to conditionally toggle the viewTransitionName
parameter according to the objective URL.
Transitioning Between Symbol States
It’s time for the 3rd and ultimate transition we recognized for this situation: transitioning the product picture on a product main points web page to a bigger view. It’s in fact much less of a transition between perspectives than it’s transitioning between two states of the picture detail.
We will in fact leverage the similar UI transition we created for the picture gallery within the ultimate article. That article demonstrated methods to transition between two snapshots of a component — its “previous” and “new” states — the use of a grid of pictures. Click on a picture, and it transitions to a bigger scale.
The one distinction this is that we need to adapt the paintings we did in that instance to React for this situation. Differently, the principle thought stays precisely the similar as what we did within the ultimate article.

Jake has really useful the use of React’s flushSync
operate to make this paintings. The operate forces synchronous and quick DOM replaces within a given callback. It’s intended for use sparingly, but it surely’s ok to make use of it for operating the View Transition API as the objective part re-renders.
// Assigns view-transition-name to the picture sooner than transition runs
const [isImageTransition, setIsImageTransition] = React.useState(false);
// Applies fixed-positioning and full-width picture types as transition runs
const [isFullImage, setIsFullImage] = React.useState(false);
/* ... */
// State replace operate, which triggers the DOM replace we need to animate
const toggleImageState = () => setIsFullImage((state) => !state);
// Click on handler operate - toggles each states.
const handleZoom = async () => {
// Run API provided that to be had.
if (report.startViewTransition) {
// Set picture as a transition detail.
setIsImageTransition(true);
const transition = report.startViewTransition(() => {
// Observe DOM updates and drive quick re-render whilst.
// View Transitions API is operating.
flushSync(toggleImageState);
});
wait for transition.completed;
// Cleanup
setIsImageTransition(false);
} else {
// Fallback
toggleImageState();
}
};
/* ... */
With this in position, all we truly must do now could be toggle magnificence names and think about transition names relying at the state we outlined within the earlier code.
import React from "react"; import { flushSync } from "react-dom"; /* Different imports */ const Main points = () => { /* React state, click on handlers, util purposes... */ go back ( <> <segment className="merchandise"> {/* ... */} <article className="item__layout"> <div>
<button
onClick={handleZoom}
className="item__toggle">
<img
taste={ isImageTransition ? "item-image" : "",
}
className={
isFullImage
? "item__image item__image--active"
: "item__image"
}
src={`/belongings/${class}/${identity}-min.jpg`}
alt=""
/>
</button>
</div>
{/* ... */}
</article>
</segment>
<apart
className={
isFullImage ? "item__overlay item__overlay--active" : "item__overlay"
}
/>
</>
);
};
We’re making use of viewTransitionName
at once at the picture’s taste
characteristic. We will have used boolean variables to toggle a CSS magnificence and set a view-transition-name
in CSS as an alternative. The one explanation why I went with inline types is to turn each approaches in those examples. You’ll be able to use whichever way suits your venture!
Let’s spherical this out by means of refining types for the overlay that sits at the back of the picture when it’s expanded:
.item__overlay--active {
z-index: 2;
show: block;
background: rgba(0, 0, 0, 0.5);
role: constant;
most sensible: 0;
left: 0;
width: 100vw;
top: 100vh;
}
.item__image--active {
cursor: zoom-out;
role: absolute;
z-index: 9;
most sensible: 50%;
left: 50%;
change into: translate3d(-50%, -50%, 0);
max-width: calc(100vw - 4rem);
max-height: calc(100vh - 4rem);
}
Demo
The next demonstrates simplest the code this is at once related to the View Transitions API in order that it’s more uncomplicated to check out and use. If you wish to have get entry to to the entire code, be at liberty to get it in this GitHub repo.
Conclusion
We did a large number of paintings with the View Transitions API in the second one part of this transient two-part article sequence. In combination, we applied full-view transitions in two other contexts, one in a extra conventional multi-page utility (i.e., web page) and some other in a single-page utility the use of React.
We began with transitions in a MPA since the procedure calls for fewer dependencies than running with a framework in a SPA. We had been in a position to set the default crossfade transition between two pages — a class web page and a product web page — and, within the procedure, we discovered methods to set view transition names on features after the transition runs to stop naming conflicts.
From there, we implemented the similar thought in a SPA, this is, an utility that incorporates one web page however many perspectives. We took a React app for a “Museum of Virtual Wonders” and implemented transitions between complete perspectives, reminiscent of navigating between a class view and a product view. We were given to look how react-router — and, by means of extension, react-router-dom — is used to outline transitions sure to express routes. We used it no longer simplest to set a crossfade transition between class perspectives and between class and product perspectives but additionally to set a view transition call on UI features that still transition within the procedure.
The View Transitions API is strong, and I am hoping you spot that once studying this sequence and following at the side of the examples we lined in combination. What used to take a hefty quantity of JavaScript is now a moderately trivial job, and the result’s a smoother person revel in that irons out the method of transferring from one web page or view to some other.
That stated, the View Transitions API’s energy and ease want the similar degree of care and attention for accessibility as some other transition or animation on the internet. That comes with such things as being aware of person movement personal tastes and resisting the temptation to place transitions on the entirety. There’s a effective steadiness that includes making obtainable interfaces, and movement is definitely integrated.
References

(gg, yk)
[ad_2]