Web Navigation Transitions

Wow, so it’s been over a year since I last blogged. Lots has happened in that time, but I suppose that’s a subject for another post. I’d like to write a bit about something I’ve been working on for the last week or so. You may have seen Google’s proposal for navigation transitions, and if not, I suggest reading the spec and watching the demonstration. This is something that I’ve thought about for a while previously, but never put into words. After reading Google’s proposal, I fear that it’s quite complex both to implement and to author, so this pushed me both to document my idea, and to implement a proof-of-concept.

I think Google’s proposal is based on Android’s Activity Transitions, and due to Android UI’s very different display model, I don’t think this maps well to the web. Just my opinion though, and I’d be interested in hearing peoples’ thoughts. What follows is my alternative proposal. If you like, you can just jump straight to a demo, or view the source. Note that the demo currently only works in Gecko-based browsers – this is mostly because I suck, but also because other browsers have slightly inscrutable behaviour when it comes to adding stylesheets to a document. This is likely fixable, patches are most welcome.


 Navigation Transitions specification proposal

Abstract

An API will be suggested that will allow transitions to be performed between page navigations, requiring only CSS. It is intended for the API to be flexible enough to allow for animations on different pages to be performed in synchronisation, and for particular transition state to be selected on without it being necessary to interject with JavaScript.

Proposed API

Navigation transitions will be specified within a specialised stylesheet. These stylesheets will be included in the document as new link rel types. Transitions can be specified for entering and exiting the document. When the document is ready to transition, these stylesheets will be applied for the specified duration, after which they will stop applying.

Example syntax:

When navigating to a new page, the current page’s ‘transition-exit‘ stylesheet will be referenced, and the new page’s ‘transition-enter‘ stylesheet will be referenced.

When navigation is operating in a backwards direction, by the user pressing the back button in browser chrome, or when initiated from JavaScript via manipulation of the location or history objects, animations will be run in reverse. That is, the current page’s ‘transition-enter‘ stylesheet will be referenced, and animations will run in reverse, and the old page’s ‘transition-exit‘ stylesheet will be referenced, and those animations also run in reverse.

[Update]

Anne van Kesteren suggests that forcing this to be a separate stylesheet and putting the duration information in the tag is not desirable, and that it would be nicer to expose this as a media query, with the duration information available in an @-rule. Something like this:

I think this would indeed be nicer, though I think the exact naming might need some work.

Transitioning

When a navigation is initiated, the old page will stay at its current position and the new page will be overlaid over the old page, but hidden. Once the new page has finished loading it will be unhidden, the old page’s ‘transition-exit‘ stylesheet will be applied and the new page’s ‘transition-enter’ stylesheet will be applied, for the specified durations of each stylesheet.

When navigating backwards, the CSS animations timeline will be reversed. This will have the effect of modifying the meaning of animation-direction like so:

and this will also alter the start time of the animation, depending on the declared total duration of the transition. For example, if a navigation stylesheet is declared to last 0.5s and an animation has a duration of 0.25s, when navigating backwards, that animation will effectively have an animation-delay of 0.25s and run in reverse. Similarly, if it already had an animation-delay of 0.1s, the animation-delay going backwards would become 0.15s, to reflect the time when the animation would have ended.

Layer ordering will also be reversed when navigating backwards, that is, the page being navigated from will appear on top of the page being navigated backwards to.

Signals

When a transition starts, a ‘navigation-transition-startNavigationTransitionEvent will be fired on the destination page. When this event is fired, the document will have had the applicable stylesheet applied and it will be visible, but will not yet have been painted on the screen since the stylesheet was applied. When the navigation transition duration is met, a ‘navigation-transition-end‘ will be fired on the destination page. These signals can be used, amongst other things, to tidy up state and to initialise state. They can also be used to modify the DOM before the transition begins, allowing for customising the transition based on request data.

JavaScript execution could potentially cause a navigation transition to run indefinitely, it is left to the user agent’s general purpose JavaScript hang detection to mitigate this circumstance.

Considerations and limitations

Navigation transitions will not be applied if the new page does not finish loading within 1.5 seconds of its first paint. This can be mitigated by pre-loading documents, or by the use of service workers.

Stylesheet application duration will be timed from the first render after the stylesheets are applied. This should either synchronise exactly with CSS animation/transition timing, or it should be longer, but it should never be shorter.

Authors should be aware that using transitions will temporarily increase the memory footprint of their application during transitions. This can be mitigated by clear separation of UI and data, and/or by using JavaScript to manipulate the document and state when navigating to avoid keeping unused resources alive.

Navigation transitions will only be applied if both the navigating document has an exit transition and the target document has an enter transition. Similarly, when navigating backwards, the navigating document must have an enter transition and the target document must have an exit transition. Both documents must be on the same origin, or transitions will not apply. The exception to these rules is the first document load of the navigator. In this case, the enter transition will apply if all prior considerations are met.

Default transitions

It is possible for the user agent to specify default transitions, so that navigation within a particular origin will always include navigation transitions unless they are explicitly disabled by that origin. This can be done by specifying navigation transition stylesheets with no href attribute, or that have an empty href attribute.

Note that specifying default transitions in all situations may not be desirable due to the differing loading characteristics of pages on the web at large.

It is suggested that default transition stylesheets may be specified by extending the iframe element with custom ‘default-transition-enter‘ and ‘default-transition-exit‘ attributes.

Examples

Simple slide between two pages:

[page-1.html]

[page-1-exit.css]

[page-2.html]

[page-2-enter.css]


I believe that this proposal is easier to understand and use for simpler transitions than Google’s, however it becomes harder to express animations where one element is transitioning to a new position/size in a new page, and it’s also impossible to interleave contents between the two pages (as the pages will always draw separately, in the predefined order). I don’t believe this last limitation is a big issue, however, and I don’t think the cognitive load required to craft such a transition is considerably higher. In fact, you can see it demonstrated by visiting this link in a Gecko-based browser (recommended viewing in responsive design mode Ctrl+Shift+m).

I would love to hear peoples’ thoughts on this. Am I actually just totally wrong, and Google’s proposal is superior? Are there huge limitations in this proposal that I’ve not considered? Are there security implications I’ve not considered? It’s highly likely that parts of all of these are true and I’d love to hear why. You can view the source for the examples in your browser’s developer tools, but if you’d like a way to check it out more easily and suggest changes, you can also view the git source repository.

7 thoughts on “Web Navigation Transitions

  1. My first reaction to reading this:

    Navigation transitions will be specified within a specialised stylesheet. These stylesheets will be included in the document as new link rel types.

    Was this: Why? This should be encoded in an at-rule, not in a link element.

    I’m glad Anne pointed this out, but I don’t understand the requirement that these rules be in a separate stylesheet from any other rules.

  2. Sorry. It looks like I parsed this completely the wrong way:

    Anne van Kesteren suggests that forcing this to be a separate stylesheet and putting the duration information in the tag is not desirable

    If I understand it now, you’re saying that Anne suggested that both of these are an undesirable way to do things. I originally interpreted it as do force it to be a separate style sheet, but don’t use link elements. I think my brain relocated the “that” in the above sentence, moving it from before “forcing” to after “and”. Sorry about that.

  3. Chris, interesting proposal! Curious, have you considered any scenarios where an exit/entry transition can be triggered at points other then “page finished loading” – e.g. in parallel with a navigation, or after some timeout? For local apps (like Gaia) the latency is not a problem, so waiting for the other page to be “ready” is likely not a problem.. but that doesn’t hold for the broader web use case, where latencies can be quite high, and where a transition can actually help “hide” some of that latency.

    • Indeed, one of the revisions I want to make to the spec is a keyword to define when the transition should start – either on-load or immediate (also, z-index of the page, to decide stacking order, rather than hard-coded). I’ll probably update the spec in git tomorrow 🙂

  4. I am very mixed over this. Introducing animation isn’t always a good thing. It can provide a richer experience for certain, but for some users (like myself – I have a vestibular disorder) it can cause them to become physically ill. The proposed solution by Google is great because it is backwards compatible. If in implementing this api a browser maker gives the user control (or better yet respects system settings for animation) to turn these on and off, then I will support them. However, all too often the user doesn’t get that kind of control and developers go overboard with the transitions.

    • My solution is also backwards compatible – in the absence of support for the new keyword, you just have no transitions, same as the (now defunct, I think?) Google proposal. A user agent could easily turn off all navigation transitions. Vestibular disorder isn’t something I’d come across before, how does it affect scrolling and your more general use of the web and computers?

  5. Promissing, at least for PowerPoint-Enthusiast 😉 Think, that this would be better allowed to Web Applications, that will soon follow native apps in stores. At time of writing this lines Apple as well as Google implement what Microsoft does with their “Project Westminster” and “Project Astoria”: They build bridges to the iOS and Android system and ecosphere, but in case of Google and Apple they work on successor systems that make an web app behave as a native one, without any third party components in between. As Westminister and Astoria, they will work out of the box and bring html,js,css seamlessly into app stores. And because both build on top of webkit, both will behave the same, only calling the view diffrent, activity, pages or whatever. Point is: This is like a splash screen, a nice to have, another place to place to place marketing material and to satisfy their department. To the web that would mean a new kind of interstitials. And in most cases: Lost time. If, in any way, this would bring some value to the people the content is produced for, for example show them what they are waiting, a short introduction, a thumbnail, … and all that with a little piece of css, that would be great. But as a pessimist, i doubt that this is used in behave of the ux only and delivers a ton of opportunity for people missinterpreting browser features as business use cases. :/

Leave a Reply