w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.38k stars 643 forks source link

[css-view-transitions-2] MPA: 'back' transitions #8685

Open jakearchibald opened 1 year ago

jakearchibald commented 1 year ago

Transitions tend to happen in the opposite direction on 'back' navigations.

With SPA, we recommend looking at state in the navigation API, and setting a class name on the root.

For MPA, it feels like we should have something higher-level:

@media (vt-nav-type: back) {
  /* … */
}

We should also look at ways to add that behaviour for SPAs:

document.startViewTransition({
  isBackNavigation: true,
  update: callback,
});

Or we could look at a tighter integration with the navigation API.

noamr commented 1 year ago

Is this for when the animations are custom, right? With the default transform/cross-fade-style animations things should "just work" IIUC. I would like to get a more detailed use case for this issue to see that we're on the same page.

jakearchibald commented 1 year ago

Yeah, but cross fade is the default because it's a neutral starting point to build from. It isn't a good transition in of itself.

See the simple shared-axis demo from https://developer.chrome.com/docs/web-platform/view-transitions/#simple-customization - as soon as you introduce a direction into the transition, you want the other direction when going 'back'.

noamr commented 1 year ago

Note that this is possible to achieve with a bit of JS even for MPA. Though of course a declarative solution would be much preferable.

For example, this PoC would slide from the top when going forward, from the bottom when going backwards, and fade in when reloading:


    switch (performance.getEntriesByType("navigation")[0].type) {
        case "reload":
            document.documentElement.dataset.navDirection = "reload";
            break;
        case "back_forward": {
            const prev = sessionStorage.getItem("prev-url");
            console.log(prev, document.referrer)
            document.documentElement.dataset.navDirection = document.referrer === prev ? "forward" : "back";
            break;
        }
        default:
            document.documentElement.dataset.navDirection = "forward";
    }

    sessionStorage.setItem("prev-url", location.href)
@keyframes slide-in {
  from { transform: translateY(-100%) }
  to { transform: none}
}

@keyframes slide-out {
  from { transform: translateY(100%) }
  to { transform: none}
}

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

::view-transition-group(root) {
  animation-name: slide-in;
  animation-duration: 1s;
}

html[data-nav-direction="back"]::view-transition-group(root) {
  animation-name: slide-out;
  animation-duration: 1s;
}

html[data-nav-direction="reload"]::view-transition-group(root) {
  animation-name: fade-in;
  animation-duration: 1s;
}
Que-tin commented 1 year ago

@noamr I think updating it here to PerformanceNavigationTiming would make sense as well.

noamr commented 1 year ago

@noamr I think updating it here to PerformanceNavigationTiming would make sense as well.

Done, thanks!

matthewp commented 11 months ago

Hello, I implemented Astro's VT support and would love to see a CSS solution for backwards animations. We currently use a data attribute on the root in order to do this, but for MPA mode there will need to be something built-in of course. I like the media query idea. Another pseudo-selector could work as well.