!!DEPRECATED!!
Going back to the original use case for types. We have a music app with 4 pages:
- Home
- Playlist
- What's new
- Song
The following transitions are designed:
- Switching between home/playlist/what's new should have a transition where the whole page slides to the left.
- Going "back" should slide to the right instead.
- Moving from song to/from home should fade the song in/out
- Moving from playlist to/from song should expand the song thumbnail to the full artwork hero.
- Reordering the playlist has its own transition.
So we define several transition types:
- slide-left
- slide-right
- song-fade
- song-expand
- list-reorder
The page itself has an class on the HTML element for which page this is (.home, .playlist, .song).
To do this in SPA:
function resolveTransitionType(currentURL, newURL, navigationType) {
if ((currentURL.pathname === "/playlist" && newURL.pathname === "/song")
|| (currentURL.pathname === "/song" && newURL.pathname === "/playlist"))
return "song-expand";
else if (currentURL.pathname === "/song" || newURL.pathname === "/song")
return "song-fade";
else if (navigationType === "back")
return "slide-right";
else
return "slide-left";
}
function navigateWithTransition(url, navigationType) {
document.startViewTransition({
update: () => navigate(newURL, navigationType),
types: [resolveTransitionType(new URL(location.href), url, navigationType)]
});
}
function reorderList() {
startViewTransition({update: () => sortList(), types: ["list-reorder"]});
}
html:active-view-transition(song-expand) {
&.song img.artwork { view-transition-name: song }
&.playlist li.item.current img.artwork { view-transition-name: song }
}
html:active-view-transition(song-fade) {
&.song article.song { view-transition-name: article }
}
html:active-view-transition(slide-left, slide-right) {
::view-transition-group(*) {
animation-name: slide;
}
&:active-view-transition(slide-right) {
animation-direction: reverse;
}
}
To do this in MPA, put this in all pages:
@view-transition {
navigation: auto;
type: slide-left;
}
@view-transition {
navigation: back;
type: slide-right;
}
@view-transition {
navigation: auto;
from: "/song";
type: song-fade;
}
@view-transition {
navigation: auto;
to: "/song";
type: song-fade;
}
@view-transition {
navigation: auto;
from: "/playlist";
to: "/song";
type: song-expand;
}
@view-transition {
navigation: auto;
from: "/song";
to: "/playlist";
type: song-expand;
}
Without from
/ to
, but with mutable types and events:
@view-transition {
navigation: auto;
}
function resolveTransitionType(oldURL, newURL, navigationType) {
// same as in SPA
}
window.addEventListener("reveal", event => {
if (event.viewTransition && navigation.activation.from)
event.viewTransition.types = [
resolveTransitionType(navigation.activation.from.url,
navigation.activation.entry.url,
navigation.activation.type)];
});
window.addEventListener("outboundviewtransition", event => {
event.types = [resolveTransitionType(new URL(location.href), new URL(event.url), event.navigationType)]
})
The use-case: a page where elements transition to each other, but only if they're loaded. If the page is only partially loaded without those elements, the whole root elements transitions with a fade.
Old document:
@view-transition {
navigation: auto;
type: morph;
}
::active-view-transition(morph) {
#some-element-1 {view-transition-name: foobar}
}
New document:
<style>
@view-transition {
navigation: auto;
type: fallback;
}
::active-view-transition(fallback) {
::view-transition-group(*) {
animation: none;
}
::view-transition-group(root) {
animation-name: fade;
}
}
::active-view-transition(morph) {
.some-element-2 {view-transition-name: foobar}
}
</style>
<!-- a whole bunch of content, progressively loaded-->
<div class="some-element-2">stuff</div>
<style>
@view-transition {
navigation: auto;
type: morph;
}
</style>
We have an app that has a simple slide between pages, and a can be accessed from a landing page. If accessed from the landing page it should morph the hero image instead of slide.
Landing page:
img.hero { view-transition-name: hero }
@view-transition { navigation: auto }
App:
@view-transition {
navigation: auto;
type: entry;
}
html:active-view-transition(slide) {
::view-transition-group(*) { animation-name: slide }
}
html:active-view-transition(entry) {
::view-transition-group(*) { animation-name: fade }
}
If the app itself is an MPA:
@view-transition {
navigation: auto;
type: slide;
}
If we have from
:
@view-transition {
navigation: auto;
from: "/landing";
type: entry;
}
Or if we don't have from
:
window.addEventListener("pagereveal", ({viewTransition}) => {
if (viewTransition && navigation.activation?.from === "/landing")
viewTransition?.type = "entry";
})
We have an app where the whole app slides way when switching between pages, but popups expand in while the rest of the page blurs and zooms out. Note that the whole page participates in the popup transition, it's not exactly a "scoped element transition".
@view-transition {
navigation: auto;
type: slide;
}
html:active-view-transition(slide) {
::view-transition-group(root) { animation-name: slide }
}
html:active-view-transition(expand-popup) {
::view-transition-group(root) { animation-name: zoom-out }
::view-transition-group(popup) { animaiton-name: expand }
}
// If an SPA
function switchPage(url) {
document.startViewTransition({update: router.switchPage(url), types: ["slide"]})
}
function showPopup() {
document.startViewTransition({update: () => {...}, types: ["expand-popup"]})
}
Found this via search, so I may miss some context. But the syntax @view-transition ( type: ) doesn't seem to work at all on MPA.
"types:" does work, but not singular "type:"
Also "from:" and "to:" do not. What's going on here? (Chrome 130)