W3C

– DRAFT –
Page transitions in the browser (Shared Element Transitions) - TPAC 2022 breakout

14 September 2022

Attendees

Present
dholbert, khush__, wendyreid
Regrets
-
Chair
Jake_Archibald
Scribe
fantasai

Meeting minutes

Slideset: https://www.w3.org/2022/09/14-pagetransitions-minutes.html

Shared Element Transitions

https://drafts.csswg.org/css-shared-element-transitions-1/

JakeA: I have slides and words, but if anyone wants to ask a question at any point, please do

[dicussion of sending slides to www-archive]

JakeA: Trying to convince Chrome to implement for years, and now we are, so I'm really excited!
… Here's some demos
… This kind of thing isn't just fancy visual, it helps the navigation
… gives a sense of whether going backwards or forward, whether something is adjacent or something
… gives a sense of motion
… whereas on the Web, navigation is just a click and a change
… maybe with an exciting flash of white
… but for a long time couldn't have nice things on the Web

JakeA: One reason why page transition is hard, because involves old thing and new thing both on the screen at the same time
… no opportunity for them to work together
… but that's only true for tranditional web application

JakeA: Single-page apps can have both states on at the same time
… but even there we don't see very many cool transitions
… because it's very difficult
… Consider a cross-fade: there's a time where both states are in the apge at the same time
… hard to do with frameworks
… if doing manually, lots of accessibility pitfalls, scroll position sync problems, if contains an iframe how to handle duplicate DOM elements...
… It's not impossible, but really difficult

JakeA: Another case, I want this box to go from one container to another, difficult because of overflow:hidden
… end up having to take element into child of root, and have to change how you write your styles
… really not easy

JakeA: Meanwhile Android/iOS there are dedicated APIs
… We think that's not fair, want to do this stuff, too.

JakeA: We're not even the first to try
… there was a proposal from 2015 from Chrome, another from Mozilla
… TabAtkins in 2018
… Tried using <portal>
… And here we are in 2022!
… Most exciting bit of history is Internet Exporer in 199?, where you could have page transitions (see http-equiv codes)
… We wanted to do better than that

JakeA: Consider this basic site, I'll show you what new API can do
… this is a single page web app, that's what Canary supports right now, but should expand to multipage
… people are more excited about cross-document navigation, but will work on that next

JakeA: This is an example of how navigation is handled in SPA world
… you catch some data, use that data to update the state
… With new API we'll add a transition to that
… document.createTransition to create the transition if not there yet
… and then apply the DOM change
… and it gives us a nice cross-fade between the pages
… Not super interesting but it is the default
… We let devs customize this

JakeA: When we call page transition, browser takes a screenshot
… so we can change DOM underneath without calling flash of unstyled content
… and then creates image of incomig tree
… and it creates a tree of elements

<transition-container>

<image-wrapper>

<outgoing-image/>

<incoming-image/>

</>

</>

JakeA: This pseudo-element structure is sitting over the top of everything
… outgoing image fades from opacity 1 to 0, incoming the opposite, and that gives you the cross-fade
… and when this is done, reveals new DOM underneath
… THis is built of platform primitives so you can play around with them
… came up with some pseudo-elements to represent these
… can bikeshed later

JakeA: We could do things like, what if instead of cross-fade we want something different
… this is all built on top of animations
… change animation-duration to 5s and now it's slower!
… gives us the opportunity also to change the animation completely
… Here's one that slides to the left, and another slides from the right
… keyframes for each
… and now for the outgoing image we apply slide-to-left
… and incoming image slide-to-right
… and now you see something more like a smoother thing from a native app
… (promise much smoother on my comp than on Zoom)

JakeA: This is somewhat not ideal if going back,
… might want differnet keyframes depending on direction

JakeA: The thing that's odd is the head sliding in and out, it's a consistent part of both these states
… we can handle that
… have page-transition-tag: site-header;
… containe: layout
… This changes how the page is captured. Now we're capturing in two parts
… header part and the rest

JakeA: So now just like we had this structure for root of page, we have one for this specific part
… can give it specific calls
… and can animate them independently
… but the default, without adding anything addition
… slide and cross-fade

astearns: what happens if not appropriate contain?

JakeA: Right now, we won't perform the transition
… we'll still call the callback for you to make the DOM change
… Designed the API so that the transition is purely an enhancement
… so if hit case where can't do a transition, still do the DOM change
… Also the same if you tag two elements with the same page transition case
… because supposed to be unique

fantasai: If I tag a piece, does it get screenshotted into the main page and therefore get drawn twice?

JakeA: It's pulled out into a separate layer, not there in the root
… so the thing we animated before, it no longer contains the header

fantasai: If tag two elements, does it fail as if not tagged, or fail the whole transition?

JakeA: fail the whole transition, only get the DOM change

khush__: This was one open question we discussed, 2 parts for script API contract, one that animation will happen
… and then callback to browser that you want to update DOM
… until your callback running, we don't update the page so can see the old DOM
… whether makes sense to do the same rendering/freezing part
… we don't do the generation of the pseudo-elements

<astearns> I think it might be better to find a way to allow ident duplication somehow.

fantasai: I'm wondering if you want to allow duplicate names, and just index them to disambiguate
… e.g. might have a bunch of elements all the same type, and want them to transition

JakeA: Thought about that, but
… suppose you had chat messages and transitioning
… in that case you want to anchor to the last message
… then need to match them in reverse order
… so that's tricky
… maybe could just index in reverse

dholbert: Question about paint ordering
… your two simple examples, one with cross-fade and one with a slide animation
… it sounded from description that the actual painted content isunderneath those layers
… what would happen if you got the slide animation too long
… if delayed the slide in, would you see a bit of the new DOM underneath?
… similar for cross-fade, at 50% would you see partially-transparent underneath?

JakeA: We solved cross-fade case by new blend mode
… that handles the 50% case
… for other case, we don't draw the DOM underneath

khush__: If tagged as shared element, it is not painted in the actual DOM
… idea that this content is being displayed through pseudo-snapshot instead
… during the transition, it effectively has 'visibility:hidden'.
… it won't hit-test, or paint in actual DOM

JakeA: This is transition we've got so far
… header which cross-fades, and root which slides
… One thing that makes it even better, I can give a page transition to the bit of text in the header
… Split it out further
… by adding a page-transition-tag to site-title
… Result is that the page moves to the side to make space fo rthe back button
… So take from the old postioin to new position
… see the text slide across since in different position from before state to after state

smfr: Would love to see this in slow motion
… so we can see what's moving where

[demo]

JakeA: In that case we've got three shared elements: title, header, and root
… example inside moving from one container to another, that isn't a problem because everything is a sibling of root

JakeA: Looking good, now let's look at desktop
… it's more nauseating, but devs can solve this with media queries
… and use a different set of keyframes
… In this case we have slide to the side animation in mobile
… whereas on desktop, does a much smaller fade-in using MQ

JakeA: Here I'm skipping transition altogether if browser doesn't support API
… can also skip if prefers-reduced-motion
… or alternatively use a simpler animation if prefers-reduced motion

JakeA: New example, going ot take that large video, and make it its own thing
… This only exists on this page
… doesn't exist on thumbnail page
… Let's say this is JS for when thumbnail is clicked
… I'll assign this a page-transition tag just for that SPA navigatio
… when video is clicked, the thumbnail expanded into the video
… so didn't matter that these are different elements in the DOM
… using page-transition-tag, told the API to treat them as being the same thing
… transition the position and size from before to after

fremy: Good moment for my question
… which is exactly related to videos and more interactive content
… if I understand correctly, both initial and final state are static images?

JakeA: outgoing stage is just a static screenshot
… but incoming is live

fremy: great, because was going to ask about that
… it would only work for videos if they kept working as they transition

JakeA: For that kind of transition, in your CSS you would hide the outgoing image
… and show the incoming one straightaway

smaug: what if incoming image, its contents are cross-origin iframe
… how do you know you have something to paint?
… [missed details]

JakeA: when you call createTransition, that can be async
… you can choose to hold back until things load

smaug: so iframe would still run animationFrame callbacks

JakeA: yes

smaug: because currently [missed]

khush__: Question is that when doing transition,embedding an iframe, during term when RAF callbacks are suppressed [missed again]

smaug: ...

khush__: Maybe this needs to be specced more clearly. we say rendering is suppressed for page that is transitioning, maybe say RAF is also suppressed

JakeA: In the rendering steps of the event loop, when rendering is frozen, what does that exactly mean
… rendering steps, do we just block "update view" or something else
… my preference would be just that last line

smfr: When you run, under author or UA control?

JakeA: author calls createTransition
… we then go and capture the state of the current page
… that's UA control
… we then call the updateDOM callback, which returns promise
… that's under developer's control

smfr: In your examples, the target page is always well-controled and static
… but pages are dynamic, they load asynchronously, they run script, etc.
… when you're animating pieces into final positions, how do you know that the new position hasn't changed under you?

JakeA: if something is going to move in the page, we'll update the final position in our default generatd keyframes at the very least
… still trying to figure if it should be more complicated than that or not
… if only updating final keyframe, will cause a jump

smfr: Other thing is page can scroll
… destination position in document-relative coords or something positioN:fixed shoooting for a fixed location?

JakeA: when we're capturing it's in viewport coords
… think of element captured as psoition:fixed
… if something scrolls underneath, treat as changing the final keyframe
… if user tries to scroll, it's not going to land on the scrollbar
… we'll capture that in the pseudo-element and prevent scrolling
… but of course JS can do it
… Could be more like CSS transitions, more dynamically changing the animations
… Our advice to devs is to reduce layout shift during page load
… I would worry about a case where dev had created, and we were hiding all their shifting
… would look good, but people with prefers-reduced-motion would see lots of jumping

smfr: thanks

JakeA: There's a lot of freedom in the transitions you can make
… all of these demos are running Chrome Canary behind a flag
… have an origin trial for it, and some dev docs
… and we have a spec, currently ED in the CSSWG
… along with some to-dos

JakeA: Next steps is feedback from vendors. This is when we want it!
… aready some feedback from FF folks, some questions about our pseudo-element tree structure

JakeA: this is our JS API, not perfect, but only a bikeshedding session away from good
… a bit concern about use of Transition where we're using CSS Animations
… so we've got some naming issues to solve
… and some minor questions on when we need promises to resolve
… We have a finish promise, what if doesn't play through before interrupted by another transition?
… These are our questions now

fantasai: What's next steps to multi-page transitions?

JakeA: next slide!

JakeA: We do capture of old state and new state, that model works
… for both SPA and MPA
… what we need is some bit of JS to provide an opt-in
… so both pages are happy with this transition going ahead

JakeA: this is a sample API,
… would only allow for same-origin document swaps
… maybe and a "pagehide" listener
… other side have an event, preveious page wants to do a transition
… opt into that
… Unfortunately can't use pageshow, because for new documents that fires after load
… so need some new events
… and would want to fire this before first render
… so would need inline JS to some degree, but we don't want to block rendering any longer than necessary

fremy_: [missed question]

JakeA: Need to know which to assing a page transition tag to
… it means you can create different transitions between different page types

fremy_: instead of that, maybe when you say "allow a transition", provide the list of stuff that you provide images for
… and new page could read that list
… get all the stuff

JakeA: we have a GH issue open
… for SPA also interesting to know what was actually captured
… and maybe give easier access to auto-generated keyframes
… e.g. want to use your own animations, but have our info from start and end positions

fremy_: URL might not always be relevant
… some hybrid pages are like SPA and sometimes new page

JakeA: would also like to pass along a structured clonable, for abitrary data like "page type"

fremy_: that's probably more useful than URL

JakeA: we would give both, we have URL to give

JakeA: this is same origin
… discussed what we could do cross-origin
… but if we do something cross-origin would be really locked down
… maybe only root origin transition

<astearns> (replying to dholbert's zoom question)

JakeA: it's just such a massive leak
… I don't think ppl will realize how much info they're leaking by giving size of the header

khush__: another thing about Xoriign
… accessing the pseudo-tree is not an option for cross-origin
… security feedback is we don't want the pseudo-elements to be accessible to CSS or script to either of the origins
… so that the duration of animation or what it looks like is completely UA-controlled

smfr: Concerned about page that's on receiving end of a page transition
… gains some info about where you cam efrom
… if old page wants to transitions
… maybe FB is the only age on the Web that does that
… receiving page knows you came from there

JakeA: we haven't thought too much about cross-origin case
… and maybe conclusion is that it can't happen
… focusing on same-origin right now

yonatan: [missed question]

JakeA: Yes. Hope is, demos I implemented with SPA, I want to make those MPAs
… I'm more excited about that
… with SPA, taking something that's very hard making iteasier
… with MPA cases we're taking something impossible and making it possible

fremy: wondering if meta tag is a good idea.
… doesn't seem like JS is required
… in a lot of cases, just saying "I accept page transitions from same-origin domains"
… and do that declaratively

<fantasai> +1

fremy: Just a meta tag: allow same-origin transition
… and in first block of bytes, browser is immediately aware

JakeA: If transitions are simple enough that they work cross-page
… if cases where you are capturing individual elements and doing something special, need JS

fremy: Yes, if you need special code for special cases

JakeA: I'm open to that
… more we can move to declarative the better

JakeA: right now to make back animations work is to look at navigation API
… let's me know based on history indexes which is larger
… for MPA we need something else, we need a media query or something

fantasai: For back navigation, 2 ways to go back: back button in UA
… but also website itself has ways of going functionally back while actually going forward i nhistory
… would want to animate those the same in most cases

JakeA: So in pages where they do a push navigation, but conceptually going back
… are devs doing that because the current API sucks?

khush__: It's just hitting a link in the page
… could have hit back butotn and gotten to same URL

fantasai: E.g. I have breadcrumb navigation, and going up, kinda want to feel going back maybe

JakeA: kCould compare URLs

fremy: or passing a parameter

JakeA: could do with strutured ???

fantasai: but declaratively

JakeA: I see

fantasai: Would be nice to have comparison functions for URLs, if you have structured URLs can do some things without needing to run JS and or check URL maps
… and also would be useful to be able to pass params, clicking these links is "back" clicking those links is "up", etc.

yonatan: maybe using conditionals?

fremy: I was thinking maybe we can use pseuod-class on the page transition element
… e.g. ::page-transition-image-outgoing:forward/ since it's a pseudo-class/etc.

fantasai: we have link attribute, rel="", might consider passing that info to the page transition in a way that allows to select against it

fantasai: already have back/up etc. in rel, just pass it similar to how we can select against a class can select against rel
… in the pseudo-elements

JakeA: [lost stack]

JakeA: Here's a case, where pasisng an element from one element to other, but the rest are clipped by parent

[demo of passing an element from one scroll container to another]

JakeA: one idea was to say that "I want this element to be nested in its closest transitioning item"
… let's say I have scroller, remainign item
… currently everything is siblings
… but in this mode, we would nest them like this
… so if you wanted clipping coulduse 'overflow: clip' as these things move around

JakeA: Getting towards the end, last topic is pseudo-selector stuff can discussin CSSWG instead

JakeA: Any questions?

smfr: Can you control the z-order of things being transitioned?

JakeA: yes, all in top layer, and there's a container that wraps these that has the pseudo-selector of ::page-transition
… that's positoin:fixed, and children are position:absolute
… so you can use z-index just as normal

smfr: if there are 2 elements and different ordering in the old page and new page, would they flip halfway

JakeA: we pick it based on the old page

khush__: old tags are orderd in old page, if new tages added in new page they're appended

smfr: so old content is on top?

khush__: ??

smfr: [question]

JakeA: it's in top layer

khush__: topper top layer

JakeA: because we want them to work even if fullscreen mode

smfr: so can't have video preview animate into new page and then place play button on top unless it's in the old page
… consider youtube embed with play button in the made
… but suppose animate somethng looks like a poster frame, and have play button appear on top in the transition

JakeA: that's fien, you have outgoing image and incoming image, so incoming image would have the play button
… can hide old image immediately rather than cross-fade

JakeA: you can make the play button a separate thing you can transition
… fine to have one of those things only be in the incoming page
… for instance, in this example, the sidebar that you see
… between these states, it's either only incoming image or only outgoing image
… because only eists on such page

fremy: The button if it doesn't appear on the existing page, won't move along with the video
… but the nesting proposal would solve it?
… when you get nesting, can say this button belongs to this other thing

JakeA: if you have something on only one side, it wouldn't move right
… nesting would cause it to move along with its parent

JakeA: over time, any last questions?

Meeting closed.

slideshow: https://lists.w3.org/Archives/Public/www-archive/2022Sep/att-0007/set-slides.pdf

Minutes manually created (not a transcript), formatted by scribe.perl version 192 (Tue Jun 28 16:55:30 2022 UTC).

Diagnostics

Succeeded: s/Page Transitions/Shared Element Transitions/

Succeeded: s/iage/image/

Succeeded: s/... The other/JakeA: The/

Succeeded: s/fremy/Simon/

Succeeded: s/Simon/smfr/

Succeeded: s/of/inside/

Succeeded: s/::forward/:forward/ since it's a pseudo-class

Succeeded: i/Topic:/Slides: https://www.w3.org/2022/09/14-pagetransitions-minutes.html

Maybe present: astearns, fantasai, fremy, fremy_, JakeA, slideshow, smaug, smfr, yonatan