I feel like common usage for multi-page view transitions is to set up a general system for them that applies generally to all pages and elements, then let it ride.
But I just recently saw the DOM events in JavaScript and how they can be used to set a “type”. So check out the events first:
// The old / unloading page
window.addEventListener('pageswap', async (e) => {
if (e.viewTransition) {
}
}
// the new / loading page
window.addEventListener('pagereveal', async (e) => {
if (e.viewTransition) {
}
}Code language: JavaScript (javascript)
You can do anything you might want in there, but an especially interesting thing to me is that you can set the view transition type, and do so conditionally.
Customize the View Transition Type for One Particular URL
Just to clearly illustrate the point, say you want one particular page to have a different transition animation than all the rest of them. Says it’s the “Shows” page on a website at the relative URL /shows. Then we’d watch for the pagereveal event and test that URL and if it’s a match we’ll set the type:
window.addEventListener("pagereveal", async (e) => {
if (
e.viewTransition &&
document.location.pathname === "/shows"
) {
e.viewTransition.types.add("toShowsPage");
}
});Code language: JavaScript (javascript)
That toShowsPage is just an arbitrary name we’re making up to use in CSS to customize the animation when it’s set.
The “Default” View Transition
We’ve got a custom type being set, but let’s set up the default first. Something like this is neat:
::view-transition-old(main) {
animation-name: slide-out-to-left;
animation-duration: 1s;
}
::view-transition-new(main) {
animation-name: slide-in-from-right;
animation-duration: 1s;
}
@keyframes slide-out-to-left {
to {
translate: -150px 0;
opacity: 0;
scale: 0.5;
}
}
@keyframes slide-in-from-right {
from {
translate: 100vi 0;
}
}Code language: CSS (css)
In my example here, it assumes a <main> content area with view-transition-name: main; so that is the element being targeted specifically here. Now when I move pages (by just clicking regular ol’ links) I get this effect:
Using the Custom Type for a Custom Animation
When the “Shows” link is clicked and the /shows page is loaded, we’re setting the “toShowsPage” type, and this is the magic moment we can use it in CSS:
html:active-view-transition-type(toShowsPage) {
&::view-transition-new(main) {
animation: to-shows-page 1s forwards;
}
}
@keyframes to-shows-page {
from {
scale: 1.1;
translate: 0 -200px;
}
}Code language: JavaScript (javascript)
Because of the extra specificity over just ::view-transition-new, this gives us an opportunity to override the default animation here with a new set of keyframes. Now just the Shows page will come down from the top instead. See the difference:
Notes
I think it’s cool we have this level of control and interplay between JavaScript and CSS.
I first saw this in Bramus’ Cross-document view transitions for multi-page applications, which is a good resource and covers “forwards”, “backwards”, and “reload” view transition types which seems extremely practical and makes me wish were something we have native CSS access to detect.
There is a native CSS way to declare the types, but I’m not quite understanding why that is useful or important to do. All I understand so far is that any type that isn’t listed there when you do declare them invalidates them, so maybe that’s useful somehow?
I would have thought the “types” stuff would have been a bit newer, and thus lower browser support, than other view transitions stuff, but that’s wrong. MDN has JavaScript type setting as well as CSS :active-view-transition-type() as the same level of browser support as multi-page view transitions in general, that is to say, Chrome, Safari, and flagged in Firefox.