W3C home > Mailing lists > Public > www-style@w3.org > August 2021

[CSSWG] Virtual F2F 2021-07-27 Part I: Shared Element Transitions

From: Dael Jackson <daelcss@gmail.com>
Date: Mon, 16 Aug 2021 18:10:33 -0400
Message-ID: <CADhPm3vSK7Z1C03RubGf=trRzcXdjS=nW3P54qxCRVPP_qdjAQ@mail.gmail.com>
To: www-style@w3.org
=========================================
  These are the official CSSWG minutes.
  Unless you're correcting the minutes,
 Please respond by starting a new thread
   with an appropriate subject line.
=========================================


Shared Element Transitions
--------------------------

  - JakeA shared a presentation with the group about the WICG proposal
      to create the ability to do shared element transitions, including
      planning to create a declarative CSS approach to do at least a
      subset of the transitions.
      - Github for the proposal:
https://github.com/WICG/shared-element-transitions
      - Recording of the presentation:
https://www.youtube.com/watch?v=UIWZFXwAPxE
  - The group was very interested in the proposal and had several
      questions
      - There is still experimentation around how best to handle
          allowing a browser to escape out of a transition that's
          taking too long without causing breakage
      - Cross-origin shared element transitions will need to be tightly
          defined. There needs to be consideration of pixel access and
          when one page tries to access an element that's not there.
          One possible avenue is to use a timer to allow the pages to
          coordinate when transitions occur.
  - Any additional feedback or thoughts should be added to the github.
      Once a more firm proposal about the necessary CSS elements is in
      place it will be taken up by the working group.

===== FULL MINUTES BELOW ======

Agenda: https://github.com/w3c/csswg-drafts/projects/19

Present:
  Rachel Andrew
  Adam Argyle
  Rossen Atanassov
  Tab Atkins-Bittner
  L David Baron
  Christian Biesinger
  Oriol Brufau
  Daniel Clark
  Emilio Cobos Álvarez
  Elika Etemad
  Robert Flack
  Simon Fraser
  Megan Gardner
  Chris Harrelson
  Daniel Holbert
  Jonathan Kew
  Una Kravets
  Chris Lilley
  Alison Maher
  Tess O'Connor
  Morgan Reschenberg
  Florian Rivoal
  Jen Simmons
  Alan Stearns
  Miriam Suzanne
  Lea Verou

Scribe: TabAtkins
Slides scribe: fantasai

Shared Element Transitions
==========================
  github: https://github.com/w3c/csswg-drafts/issues/6464
  proposal: https://github.com/WICG/shared-element-transitions

  JakeA: [projects slides]
  JakeA: I'm helping out with this Shared Element Transitions work,
         along with Jeremy and Khushal
  JakeA: Current state: when you navigate on the web, the page just
         changes
  JakeA: but on apps, especially in mobile, you get these lovely
         transitions between states
  [slide shows various transitions, like sliding in a sidebar, swiping
   across the screen horizontally to show different panels, etc.]
  JakeA: They look nice in person, and can even be directly useful, to
         help communicate transitions between states so there's less
         context loss

  JakeA: I asked people on twitter about this, especially if they'd
         like it in a SPA or MPA (multi-page app)
  JakeA: most people were interested in it for a multi-page app!
  [slide shows Twitter survey of SPA vs MPA, 31% to 52.9%]
  JakeA: I see why - you can already kinda do it in a SPA, but it's
         impossible in an MPA
  JakeA: Strong feeling that many sites *become* SPAs just to get these
         transitions; not sure, but it feels like it.
  JakeA: And that's a problem, SPAs have a lot of issues, and they're
         often done badly.
  JakeA: But even when done by experts, you lose things like HTTP
         streaming, have to load a big JS bundle, etc.
  JakeA: So thinking about this space

  [slide shows timeline:
     2015: Chrome proposal and experiment
     2015: Chris Lord (Mozilla)'s sketch
     2017: Jake's sketch
     2018: Tab's sketch
     2021: This round!
  ]
  JakeA: 2015 was an early chrome proposal, didn't go very far, and the
         people left for other projects
  JakeA: 2017, I sketched an API. Each time we learned more things that
         might work.
  JakeA: 2018, Tab had his own proposal
  JakeA: And now we're here today
  JakeA: Not the first people to try this out, even back in '97 IE had
         something.
  JakeA: 24 years ago, you could use <meta> to do page transitions
  [1997: IE4 with navigation transitions via meta tag
         <meta http-equiv=page-enter
               content="RevealTrans(Duration=0.600, Transition=6)]"> ]
  JakeA: There were 22 transitions to choose from; several dupes from
         different directions, like "wipe left" and "wipe up"
  JakeA: also a special 23rd transition that made a random choice
  JakeA: Slightly kidding, but I think a predefined set of transitions
         can get us pretty far
  JakeA: But not all the way, I got feedback from people asking for
         custom control

  JakeA: If we look at some of the nicest transitions in the android
         docs
  JakeA: It's animating between states in multiple ways; some things
         are shared between the states
  [shows Android Contacts list, clicking on name of person shifts the
      name up and colors/layout changes to show their profile above/
      below ]
  JakeA: This person's name in the address list moves to be the header
         for their profile
  [Jake shows his homepage with 2-line title vs 3-line title]
  JakeA: On my blog, when you're on the index page and click thru to an
         individual post, the headers are basically the same. Why
         couldn't that transition?
  JakeA: Every element on the two pages are different, even different
         tag names.
  JakeA: Some elements change content, some elements (dates) don't
         change content but do change position.
  JakeA: Header changes layout, it does a fade to the new larger text
  JakeA: and header container scales its height
  JakeA: then the rest of the page just fades content

  JakeA: There was a bunch of moving parts here, but overall, it was
         simple because it was done with just textures, no live layout
         between the two
  JakeA: So didn't need to keep the old page alive
  JakeA: there are some concepts we keep coming back to
  [slide: Change]
  JakeA: First, there's a change
  JakeA: But before that, we need a prepare step
  [slide: Prepare, Change]
  JakeA: where the outgoing page offers up parts of itself to be
         involved in the transition
  JakeA: Like my blog example, offering the header, the date, the
         sidebar
  JakeA: Then the change happens, letting the outgoing page be cleared
         from memory except for the textures it's offering up
  [slide: Prepare, Change, Transition]
  JakeA: Then the Transition happens, where the new page animates in
  JakeA: Like, if you have a series of chat messages, the old page
         might have three messages, the new has four; the three can
         just fade in, but the fourth has to do something special; this
         is where that can happen
  JakeA: Like I said, these are textures; we don't want to do layout on
         the old page
  JakeA: But we also don't want the new page to get pixel readback from
         the old textures
  JakeA: New page is trusting what the old page gave it - it says "this
         is a heading!" and the new page trusts that it's a heading
  JakeA: for cross-origin transitions that's a potential concern

  [slide: cross-origin transitions]
  JakeA: The old page could offer up bad stuff
  JakeA: A bad page could transition into a news page, offering up its
         "header" and boom, it's the q-anon logo
  JakeA: So cross-origin transitions either need to be heavily
         restricted
  JakeA: or need a two-way handshake to agree on which textures to share

  [slide: single-page app transitions]
  JakeA: There's also single-page app transitions
  JakeA: Not as many authors are interested
  JakeA: because they're actually quite hard to do today
  JakeA: You need DOM for both states at once, which means you need to
         protect the old stuff from being interacted with, or being
         seen by a11y tools
  JakeA: Need to control for scroll position, how it can mess up CSS
         mid-transition, etc.
  JakeA: Twitter says they don't do transitions precisely for these
         reasons
  JakeA: So we were thinking about this and realized this should work
         on the page transitions model just as well
  [slide: prepare, change, transition]
  JakeA: You're still doing a prepare phase to record bits of the old
         state, then you transition into the new state
  JakeA: We already have a sketch of the SPA model behind a flag in
         Canary
  JakeA: Here's an example of the Preact website
  [slide: Preact website SPA]
  JakeA: Author of the site says it's "a mess", but it has a router for
         the overall site transition as many SPAs do
  JakeA: But even though I didn't understand much, I could easily poke
         in and add the transitions API, and it all just works
  JakeA: Back button reverses transitions, it's all just very little
         code
  [slide: preact website with subsections fading in and out in the
          content panel]

  JakeA: In spirit, our current design is very similar to the old IE
         version, with a list of predefined transitions
  JakeA: New bit is this "shared elements" notion, like the heading and
         sidebar in the guide.
  JakeA: In this example I'm using this to keep them in position and
         only change the content by sliding it in

  [slide: Interesting Problems]
  JakeA: While we need the bare-bones for EWM reasons, I think there's
         definitely a high-level version that solves 80% of cases
  JakeA: Some problems.

  [slide: cross-fading]
  JakeA: First is cross-fading. Transitions have a lot.
  JakeA: Hard to do in CSS right now
  JakeA: Especially between elements with transparency.
  JakeA: Can use explicit opacity on the two states
  [slide with .thing1 { opacity: 1 } .thing2 { opacity: 0; } ]
  JakeA: Here's a slide where the two are identical save for a few
         extra words on the second
  [slide: cross-fade shows image, which doesn't change, but fades
          to semi-transparent halfway in the transition nonetheless ]
  JakeA: Midway thru the transition the shared pixels fade a bit,
         ideally we could fix this
  JakeA: CSS has a cross-fade(), which does the right thing
  JakeA: Which isn't always what we want
  <chris> This is because the cross-fade needs to be done in
          linear-light
  <TabAtkins> (That's not the only reason)
  <chris> so that 0.5 + 0.5 = 1.0 :)
  <TabAtkins> cross-fade() also blends sizes tho
  <chris> (interested to know the other reasons)

  [slide: background-image: cross-fade(...); ]
  [slide: Not quite elements, not quite images]
  JakeA: We're not dealing with elements *as such*; images might be
         okay since we've just got textures left over
  JakeA: but not all an image - Some information like transforms we
         might want to carry over so it can animate properly

  [slide: timings and deadlines]
  JakeA: Another thing to think about is timings and deadlines
  JakeA: Right now when you click to a new page, the browser shows the
         new page when it wants, when the data comes in
  [slide: iWouldLikeToDoAPageTransition(); ]
  JakeA: But if the incoming page wants to control the transition, it
         should be able to signal for it
  JakeA: But how long can we wait?
  [slide: iWouldLikeToDoAPageTransition(); await massiveImageLoad;
          nowDoThePageTransition(); ]
  JakeA: How long do we wait for the "i want to handle this" signal,
         and how long do we wait for it to actually do the transition
         after it signals?
  JakeA: We like progressive rendering
  JakeA: Do we want to allow pages to delay until a 5MB image loads?
  JakeA: They can do it today, kinda
  JakeA: But maybe if they, say, don't do it in 5s we just do a page
         swap

  [slide: Thoughts? Questions?]
  JakeA: So, questions?
  <JakeA> https://github.com/WICG/shared-element-transitions - repo
          (API design in flux)
  <JakeA> https://preact-with-nav-transitions.netlify.app/ - preact
          site demo

  florian: Intriguing! Overall makes sense at a high level.
  florian: Curious how much ends up being declarative vs JS, how they
           intertwine, I'm sure y'all are thinking of this
  florian: There was also something between IE4 and modern stuff. I
           believe Opera experimented around 2010
  florian: They were a little like the declarative transitions, but
           also a concept of arranging things in space, so you could
           say "this page is left of that one" and it would
           automatically swipe over to it
  florian: tied into gestures as well
  florian: Wondering if there has been any thought on these lines,
           including tied in with the "shared elements" part
  florian: This notion of arranging bits of space, I thought it was
           interesting
  florian: Doesn't seem obvious that it doesn't fit
  JakeA: Hard to talk about binary declarative vs imperative
  JakeA: For some people it just means "JS" vs "CSS", but Web
         Animations - which is it?
  JakeA: We almost certainly will end up with something declarative to
         some extent
  JakeA: Lot of desire to do this animation out of the control of
         either page; the pages just dictate how they want it to go,
         but it's actually handled outside
  JakeA: I did put a sketch together purely in CSS, and I think I got
         to 15+ properties and hadn't thought about the destination url
         negotiating yet...
  JakeA: I anticipate the destination being done in JS at least
  JakeA: And maybe there's a smaller subset that can be done in pure
         CSS with simple behaviors
  JakeA: Before I had the ability to associate elements with some ID,
         and if the destination page uses the same ID they're
         automatically tied together
  JakeA: In the JS API I presume it'll be similar.
  JakeA: There needs to be a way to give more information - like, by
         default it maybe just translates, cross-fades, and scales
  JakeA: But scaling isn't always what you want, as I showed in some
         examples

  chris: If you've got two things transitioning opacity...
  chris: You need something where .5 + .5 = 1. That needs linear light;
         images aren't linear painted, which is why there's lightening.
  TabAtkins: linear-light was one problem
  <chris> agreed
  TabAtkins: Other problem is that halfway through, two 50% things laid
             on top of each other means together they are only 75%
             opaque
  flackr: Gaming has opacity saturation buffers to solve this
  khushal: Yeah we found that, there's a blend mode that can do that
  khushal: I found a webkit bug asking to expose this to mix-blend-mode
  <khushal> https://bugs.webkit.org/show_bug.cgi?id=142416 is a bug
            which talked about the blend mode that would work for this.

  emilio: So the idea is that the destination page can observe stuff
          about the transition, like position of old elements
  emilio: That seems like in conflict with the UA being able to control
          the transition
  JakeA: We hope within the API to catch spots where, like, if an error
         is thrown it doesn't deadlock the transition
  JakeA: With this model you can definitely delay the intro of your own
         page. Having the incoming page control it means you're only
         harming your own performance
  JakeA: Question of how much we want to prevent people - they can
         already delay their own page arbitrarily.
  JakeA: Worry about damaging legit use-cases to guard against some
         people getting it wrong

  emilio: Main thing I'm concerned about is an animation working on a
          good computer, but breaking on a crappy phone
  JakeA: Right, so think if the transition isn't ready within 3s we
         just bail, or something like that
  JakeA: Like doing font-rendering intervention
  emilio: I took a look at the API, which is promise based; if you bail
          on the transition it rejects the promise, right? If the
          promise rejects unexpectedly the page might still break.
  emilio: This would be much simpler if the UA could decide what to
          render without the destination page being involved, but I
          understand it breaks some of the fanciness.
  JakeA: I see you're looking at the GH page for the API; that's still
         in flux
  JakeA: We're definitely looking at ways to mitigate these problems
  JakeA: Issue on GH right now looking at moving to a JS API similar to
         WebLocks
  JakeA: In that you provide a callback to run later that returns a
         promise. Errors become rejected promises instead of breaking
         script, so you somewhat avoid deadlock.

  khushal: Design thing I'm thinking about, which page controls the
           transition. Reasons for that to be diff between same-origin
           vs cross-origin
  khushal: Incoming page controlling the transition is good because it
           has info from both sides, and can make better decisions
  khushal: But for cross-origin cases, we can't let the incoming page
           know about the outgoing page, so the outgoing page has to
           control the transition completely
  khushal: This requires different API shapes, and it's causing some
           API divergence
  JakeA: This is something I ran into for the CSS-only version
  JakeA: If you've got a shared item in the outgoing page which doesn't
         have an incoming equivalent, or vice versa, it becomes hard to
         deal with
  JakeA: It's hard in CSS to talk about an element that isn't there
  JakeA: Whereas in a JS callback you can get handed five elements, and
         four match in the new page, and you can figure out what to do
         with the leftover

  astearns: You mentioned pixel access - I assume incoming page has no
            pixel access at all
  JakeA: Correct
  JakeA: Probably model will be outgoing picks up an element for
         sharing, and a StructuredClonable of info about it, like "I'm
         a heading" or whatever
  JakeA: But no pixel access
  JakeA: Hope we can one day get to a state where we can read the
         pixels on a page
  JakeA: We have origin isolation right now, maybe some even stricter
         version could some day allow this
  astearns: And with outgoing pages opting into data sending, for
            cross-origin the incoming page might need to be restricted
            from knowing which of its transitions actually matched. No
            info about which headings matched, etc, just always run them
  JakeA: Two angles there - don't want Page A to find info about Page B
         they didn't want to share
  JakeA: In some cases the number of chat messages can leak that
  JakeA: But there's also Page A and B *wanting* to share info, but for
         privacy we don't want to allow them
  JakeA: Not sure where the line is right now
  JakeA: Might be that cross-origin is just the IE model - a list and
         the whole view moves

  astearns: You talked about having a high-level declarative variant
            with less features
  astearns: I hope if we get there, the high-level thing can be hooked
            by the low-level, so you can intervene when necessary
  <fantasai> +1
  JakeA: Yeah, I think CSS shorthands model is something like what we
         want to go for
  JakeA: Can set up a "sliding" animation, and it can specify a
         WebAnimation-like set of keyframes
  JakeA: And maybe we just wrap that up in "slide-left" keyword, but
         with full control to do your own

  <astearns> prefers-reduced-motion would turn all of this off,
             presumably

  fantasai: One, incremental rendering, if you're on a slow connection
            you want the partial page to show up early
  fantasai: Dunno how that's considered right now, just want to make
            sure it's not forgotten

  fantasai: There was also a discussion about shared element
            transitions in Burlingame, I think, not sure if there are
            notes or if it was informal; think Ojan was involved
  fantasai: Big point I remember there was that cross-origin ones
            shouldn't leak info
  fantasai: Another idea was sharing a timer between the two, so
            outgoing and incoming pages could put things on the same
            timeline
  fantasai: Couldn't necessarily coordinate between elements, but could
            at least ensure timing matched up

  JakeA: For incremental loading, definitely one of the fundamentals I
         want to keep.
  JakeA: Definitely a tension between that and page transitions
  JakeA: Would be nice to have a way to say "don't transition until X
         element is around"
  JakeA: Very hard to do right now, tricky with a Mutation Observer
  JakeA: Might be a waitForElement() API to let you delay as little as
         possible
  JakeA: In the blog example I want *some* of the content to be there,
         but don't need the whole page necessarily. Probably want a way
         to say I just need the top of the page, not the stuff a MB away
  JakeA: Nothing concrete there yet, but it's on our minds

  JakeA: I didn't know about the transitions discussion
  JakeA: I'll try to find notes

  JakeA: In chat Alan asked about prefers-reduced-motion
  JakeA: Yeah we'd just ignore the transition in that case

  JakeA: Re: leaking cross-origin, absolutely a concern, need to lock
         down properly
  JakeA: Re: timeline sharing, that's similar to my previous 2017 idea
  JakeA: That version required both pages to be alive at the same time
  JakeA: which is an issue for low-memory devices
  JakeA: Thought right now is one side controls the transition; the
         other side just offers things to be transitioned

  khushal: Interesting to think about whether incoming page *has*
           contextual info to control the transition or not
  khushal: If you're on a news aggregator, and it wants to have a
           transition to links, ok. But if the user enters in the
           omnibox, maybe the incoming page gets control over that
           instead. Or maybe browser-initiated just doesn't get
           transitions.
  khushal: Also, re: same vs cross-origin
  khushal: In same-origin when incoming can control, we also let it
           control when the transition states
  khushal: and it gets all the info about the outgoing page, so it can
           do smart things
  khushal: but in cross-origin, when the incoming page doesn't have any
           info but might still have useful timing info, that's a
           difficult question
  eugene: Riffing on khushal's comments, if you have cross-fade
          capabilities, the omnibox can do its own thing controlled by
          the UA
  eugene: we've also got scroll-to-text capability now
  eugene: and ideally when you're referring to a shared element,
          hopefully we have a consistent way to refer to those elements

  eugene: Another comment, declarative vs imperative. Declarative is
          basically marking up a single transition, I think it falls
          down when you want multiple things simultaneously
  eugene: So it's important to have the models build on each other
  eugene: Big call for extensibility, building more on top of this
  eugene: Think the right model is to build on the animations
          ecosystem, so all the existing animations work, and users get
          new abilities as animations get better

  JakeA: re: scroll to text, I think you can use a css selector to id
         the element
  JakeA: that works okay for scroll-to-text because the lifetime is
         relatively short
  JakeA: And if the highlighting doesn't work, it's not a huge loss
  JakeA: Could be worse on transitions
  JakeA: Concern I have is you're navigating around a site, and
         mid-article the site redeploys and the class names have changed
  JakeA: So model we're using right now isn't tags or selectors, it's
         literally just a bunch of named element references
  JakeA: {"heading": someDOMEl}
  JakeA: Might need a way to bail on transitions so if two versions of
         a site are totally incompatible they can figure it out
  <jbroman> I think scroll-to-text uses a snippets of text rather than
            CSS class names to avoid this
  eugene: I think if it's a problem for page transitions, it'll be more
          of a problem for people who save links from their search bar;
          "scroll to image" is just as bad

  flackr: I assume that BF nav, we want to use the transition that you
          saw when you came in
  flackr: Not sure how it would work with the current API
  flackr: But should be some way of memorizing the transition so we can
          reverse it if we go back
  flackr: Is that something we can do?
  JakeA: Yes, and the more automatic we can do the better; people don't
         often test that
  JakeA: Maybe we only do it if the page is in BFCache
  JakeA: Gets more complicated if you're reloading the old page as well
  JeremyRoman: This is a very big rathole, but interesting
  JakeA: I think limiting it to BFCache and only +1/-1 transitions is a
         good start

  astearns: Assuming you'd like more feedback in the WICG repo?
  JakeA: Yes, that's the right place for it
  astearns: And we can do CSS issues when you come up with a
            declarative CSS version of this
  JakeA: Absolutely. Thanks!
  <jbroman> +1; thanks CSSWG for your time
  <vollick> thanks, all!
  astearns: I think it'll be great to bring the web platform back up to
            IE4 standards.

  <JakeA> https://github.com/WICG/app-history/
  <JakeA> For the minutes: https://github.com/WICG/app-history/
          provides a "navigate" event which provides a central place to
          hear about navigations, kinda like I was able to use on the
          preact site (due to its router). This means if you want to
          hear about navigations, you don't need to listen for all link
          clicks, all form submissions etc etc

<br dur=10min>
Received on Monday, 16 August 2021 22:12:14 UTC

This archive was generated by hypermail 2.4.0 : Monday, 16 August 2021 22:12:15 UTC