[CSSWG] Minutes Scroll Animations Breakout 2022-06-16

Present:
   Adam Argyle
   Antoine Quint
   Bramus Van Damme
   Elika Etemad
   Jen Simmons
   Kevin Ellis
   Miriam Suzanne
   Robert Flack
   Simon Fraser
   Tab Atkins
   Yehonatan Daniv


View Timeline Animations Brainstorming and Design Session
=========================================================
github: https://github.com/w3c/csswg-drafts/issues/7044
ScribeNick: TabAtkins

[ picking up mid-stream: prior bits were fantasai introducing the topic and 
flackr going over proposal in 
https://github.com/w3c/csswg-drafts/issues/7044#issuecomment-1144946715 ]

   fantasai: I think that's the direction I'd like to go in
   fantasai: I think would be a good idea to make sure we have the declarative
             aspect set up at the same time as the API
   fantasai: Keeping them together

   bramus: Posted a similar concept to Rob's, a bit further down the thread
   bramus: Where enter/contain/exit are nested inside the @keyframes block
   bramus: Same concept, just different syntax
   flackr: Being able to tie keyframes to offsets is I think a good direction
           to support eventually

   flackr: What does this mean for the non-keyframe part of the spec?
   flackr: Do animations still have start/end time that falls within these
           phases, or is it just keyframes?
   fantasai: Didn't understand that
   flackr: You've got a "contain" animation.
   flackr: So in keyframes say "contain:0" first keyframe, "contain:100%"
           second keyframe
   flackr: that maps to 20% and 80%, what happens before 20% and after 80%?
   fantasai: Well what do we do if you have just a 20%/80% keyframe today?
   flackr: We fill in the 0/100 values with underlying values
   fantasai: There you go
   flackr: Well, might not be what you want. Might not want the animation
           active during those phases

   antoine: I'm reading the issue, says strong use-case for element animating
            as it enters/exits
   antoine: Still talking about scroll offset, or entering/exiting via time?
   fantasai: Just scroll offset
   fantasai: Trigger by scroll offset is scroll-triggered animations. There's
             proposals for that also, but they're separate

   fantasai: Think we need a whiteboard, one sec
   [linked to whiteboard page]
   <fantasai> 
https://excalidraw.com/#room=59388d327d8f3aa8ddb2,6FU4m3Fw4huQ-JGyP23o5A
   flackr: [draws previous scenario in the whiteboard]

   Four illustrations are made:
     0% = small box just below the viewport
    20% = small box sitting just inside the viewport,
            adjoining at the bottom edge
    80% = small box sitting just inside the viewport,
            adjoining at the top edge
   100% = small box just above the viewport

   Along the side:
   - the phase between 0% and 20% is labeled "enter"
   - the phase between 20% and 80% is labeled "contain"; within it:
       - the top end of the range (20%) is labeled 0%
       - the bototm end of the range (80%) is labeled 100%
   - the phase between 80% and 100% is labeled "exit"

   flackr: Start of view tiemline might be when box edge just enters
           the viewport
   flackr: So 0% kicks in just as your scroll starts reaching the box
   flackr: These are the times the element reaches various positions in
           the viewport
   flackr: We can give these names, like "contain" for these spots where it's
           fully in the viewport, and enter/exist for when it's peeking in
   flackr: Your animation keyframes can refer to anything in these periods, and
           within each you go from 0-100%
   flackr: So if you specified an aniamtion on this timeline, and had keyframes
           at 20/80, we'd implicitly creat a 0/100 keyframe with same values by
           default

   fantasai: I think if we want to shorten where the animation is active, might
             make sense to bind the animation to a phase
   flackr: yup
   fantasai: We'd discussed having an animation-timeline-phase property
             doing this
   fantasai: So that would let it run only in the segment you want
   flackr: My counter-proposal is we think of it all as times
   flackr: So like if you set delay, it's equivalent to setting the start time
   flackr: So setting delay to "contain(0%)" it would start at the beginning of
           the contain phase

   flackr: For end delay it's relative to the end of the timeline, which
           is problem
   flackr: Good thing about this, though, is it's not a new concept. Already
           have an end time that's start+duration. We can define an end time
           that plugs into this and implies a duration
   fantasai: So we currently have animation-duration, right? The endtime is
             delay+duration?
   [yes]
   kevin: And we have implicit iteration duration - if you set start and end
          the iterations are the time between there, delay can cut into that
   fantasai: So if I have an explicit duration that'll conflict with other
             endtimes. Gotta think about interaction
   flackr: If you specify all three properties that'd be a bug, two of them
           would get precedence
   TabAtkins: follow abspos precedent, and prioritize start + duration like we
              prioritize start + height

   fantasai: Alternately the end delay might be possible if you specify, like,
             a position in the timeline, rather than a time amount
   flackr: Right, it could work out the end delay, what to subtract to reach
           that position
   flackr: Reason I suggested this was to avoid adding a "phases" concept,
           and just built it on the existing timing props

   fantasai: So we'll have an ability to bind keyframes to named points on
             the timeline
   fantasai: Do we want that in the API so you can ask where it is?
   fantasai: Can you query the phases?
   kevin: getKeyframes() does a lot of resolution. think it could have all the
          keyframe offsets resolved
   fantasai: Right, but like if you're in an animation, can ask the timeline
             "am I in the contain phase? am i past 50% of the contain phase?"
   flackr: Could add some properties to the timeline which would expose the
           current phase/portion
   flackr: Going from animation to that might be complicated
   fantasai: Well not animation setting where we are, it's the timeline that
             has phases
   flackr: So could imagine, in addition to currentTime, have a currentPhase
           and phaseTime to reflect
   fantasai: Some phases overlap, right? cover overlaps all the others?
   Kevin: Maybe a getTime() that can take a region, and it'll tell you time
          wrt that region
   fantasai, flackr: Yeah
   fantasai: And something to list phases supported by the timeline
   flackr: phases, stages, cues... good bikeshedding exercise
   fantasai: can imagine people wanting the concept of named phases in other
             timelines, including time-based
   flackr: I think brian had a suggestion in the issue
   flackr: brian suggested cue

   smfr: Another way to think about this? As two nested sets of phases?
   smfr: So sets for the enter/contain/exit phase
   fantasai: But you might have keyframes spanning across multiple phases,
             e.g. one animation running from the start to the end of the
             cover phase
   fantasai: Don't always want to break it down as finely as we are right now
   flackr: Nice thing is the thing you specify in your keyframe lives alongside
           other times, and interpolates normally
   flackr: And these phases can overlap; if you make out-of-order keyframes
           we'll just handle the same way [by re-ordering]

   smfr: Any proposal for labeled keyframes? Like an "enter" keyframe?
   fantasai: Right, that's the proposal.
   fantasai: So like "enter %" covers the space from start to end of
             enter phase
   smfr: So you need four names... enter-start, enter-end...
   flackr: Can do %s of the phases
   flackr: Look at bramus's most recent comment for an example
   <bramus> 
https://github.com/w3c/csswg-drafts/issues/7044#issuecomment-1145786838

   fantasai: wrt syntax, if we want to allow nesting, seems fine, but I think
             I'd prefer the flat list. gives you more flexibility in
             organization.
   fantasai: And if you end up with something that might end up needing
             re-sorting, easier to understand these are all cards in your
             animation timeline and will get re-sorted as needed.

   Yehonatan: would naming the phases inside the keyframes make it something
              you can't re-use back in time-based?
   yehonatan: Only usable in view-timeline?
   bramus: Yeah, similar comment. How do we let people use existing animations
           like fade-in?
   flackr: Can use start-delay and duration, referencing the points.
           `animation-delay: enter(0%); animation-duration: enter(100%);`
   fantasai: Suspect he's saying it's not very ergonomic
   flackr: Think it's actually reasonable ergo. In the longhand you can just
           set the start and end delay, it'll look like
           `animation: fade-in enter(0%) enter(100%)`
   fantasai: What if we had a way to shorthand the start and end delays
             together to make it really easy to specify "stretch across
             this phase"?
   fantasai: Like `animation-phase` could be a shorthand for just the
             start/duration, and you could say `animation-phase: enter` as
             shorthand for `animation-delay/duration`
   Kevin: timeline:enter could automatically set the delay to correspond?
   fantasai: Might have some parsing difficulty in the animation shorthand,
             will have to look at what to do to make it unambiguous
   TabAtkins: if you just supply a no-arg function, maybe that's
              distinguishable
   TabAtkins: I was assuming this would be a function this whole time, btw
   fantasai: Don't think we have a precedent for the function being a random
             custom ident
   TabAtkins: I thought the phase names were predefined?
   fantasai: Are now, but want to keep it open for user-defined later.
   flackr: so if we wanted to be explicit could have `phase(enter 0%)`
   fantasai: Maybe. We don't need it for the lognhands; we can figure it out
             later. Various disambiguation strategies

   flackr: All right. Some things to figure out, but the general direction
           seems okay
   fantasai: So going over:
   fantasai: 1) Introduce timeline phases
   fantasai: 2) API to query what phases are supported, and where you are
                in a given phase
   fantasai: 3) Keyframes can attach to a particular point in a phase
   fantasai: 4) start-delay and end-delay can ref points in time, including
                within phases
   fantasai: 5) Shorthand for those two properties making it easy to set
                start/end to a particular phase
   fantasai: 6) Figure out how to put all this into the animation shorthand
   fantasai: 7) APIs for attaching keyframes to timelines, don't remember how
                they work but something needs to be done there

   yehonatan: Q about %s in the diagram - are those numbers fixed?
   flackr: No, they're based on the layout.
   fantasai: If you have a small item and big viewport, contain might be 5% and
             95%; if you have a big item it might be 45% and 55%. Varies
             depending on layouts
   yehonatan: So size of the subject measured against the scrollport
   fantasai: Right. You want 0% to 100% of "cover" to progress linearly
             based on scrolling, so enter/exit needs to cover a variable
             percent.
   <flackr> I think enter 100% = observed_height / (scrollport_height + 
observed_height)

   miriam: There's a chance enter/exit overlap and there's no contain,
           if element is bigger than scrollport?
   flackr: Yes
   fantasai: I think we wanted to say entry ends when either the entire element
             is in viewport, *or* viewport is filled with the element, so no
             overlap.
   fantasai: Overlapping phases can screw up animations, like with a fade-in
             entry anim and fade-out exit anim, you might never get past 50%
             opacity, and that's bad
   smfr: I think that prevents you from distinguishing between an overly tall
         element and one that just fits in the viewport?
   smfr: So if enter ends when the element fully covers the viewport, you can
         scroll a bunch and still see the element, you can't target that phase?
   fantasai: That's the contain phase
   smfr: Hm, maybe confusing
   flackr: Can see going either way. We have a clear outcome of what happens
           whatever we do, since we're mapping them to times.
   fantasai: I think the natural thing to think about is how we make a
             fade-in/out anim work.  That's most basic.
   fantasai: Want it to work for that particular use-case, and related things.
             If there's other things we need to do for less common cases we can
             look into that.
   fantasai: But need to make sure fade-in/out (or similar timing models) work
   bramus: In case of overlap between enter/exit, possible to speed up frames?
   fantasai: I'm saying we won't have overlap
   Bramus: Element larger than viewport?
   TabAtkins: [shows drawing]

   smfr: If you apply animation to stickypos, how does that work?
   smfr: enter/exit based on position after resolving sticky?
   fantasai: Right
   TabAtkins: Sticky is conceptually relpos, so should work that way
   smfr: So timeline resolution is after sticky handling
   smfr: And fixed would just never animate?
   smfr: Or would it be contain?
   flackr: Can make it unresolved so animation doesn't apply
   flackr: Already the case that if start time = end time you have unresolved
           time and it doesn't run

   yehonatan: something missing is specifying according to layout
   yehonatan: so in scroll timeline you can specify offsets by px or vw o
              whatever. Here's it's completely %s based on intersection amount.
   yehonatan: Say I have insets, for example.
   flackr: We do have insets in the API, and can have equivalent for margin
           around the element
   yehonatan: so if I'm animating a stickypos that sticks to top:100px, I can
              put that 100px into the inset and have that start the
              contain phase?
   flackr: yeah
   fantasai: Might want to magically do that for stickypos so contain starts
             when you're stuck

   yehonatan: mentioned this to adam recently, you said there will be a CQ for
              stuck, right?
   argyle: Yeah, CQ for stuck.
   miram: Proposed but not yet specified

   smfr: How does this work with nested scrollers?
   smfr: Can I specify a timeline relative to a higher scroller?
   flackr: No, only the nearest scroller, always
   fantasai: If we decide we need it, that's level 2.
   smfr: How to define?
   fantasai: An ancestor that's a scroll container
   fantasai: So everything but 'overflow: visible/clip'
   smfr: We got pushback from stickypos that an enclosing overflow:hidden would
         break behavior, suspect we'll get similar here
   fantasai: We didn't have overflow:clip back then. We have that now to
             actually clip, and display:flow-root to force BFC. Reasons to do
             overflow:hidden that's not actually a scroll container are much
             less now.
   smfr: Right, just a lot of historical content that uses it.

   fantasai: So I think we have a decent path forward, anything else to
             think about?
   flackr: Should think about stickypos more.
   flackr: Another option is to make it invalid to observe stickypos relative
           to scroller, but dunno if that's good
   fantasai: Think it makes sense for fixpos. For sticky we can just inset the
             visible viewport to match the inset-modified containing block
   flackr: Yeah seems reasonable. If we add padding properties for
           this scenario,
           putting it there would make sense.
   flackr: Because insets modify the timeline, while margins modify your
           position in the timeline.
   fantasai: right

   [fantasai and flackr are happy about this]
   fantasai: We've got a lot of drafting to do.

   fantasai: Think we resolved to remove phase from the timeline API?
   fantasai: We'll need to bikeshed the name "phase" for this thing or the
             previous thing. Suspect we want the better name for this one
             as it's more user-facing. Naming discussion to be had with
             the animation people
   flackr: Yeah think we can just have a bikeshed issue
   fantasai: What phases remain in animation? just active and inactive?
   flackr: Yes
   fantasai: Maybe they can be states, and we use phases?
   bramus: +1 on that
   flackr: Animations also have phases and they fall into
           inactive/before/active/after
   Kevin?: animation-effect
   flackr: This is why timelines use the "phase" concept
   flackr: But might not make sense
   fantasai: Is that name exposed in the API or can we bikeshed all of them?
   flackr: timeline phase is not exposed
   flackr: animation phase is, I believe
   [double-checking]
   flackr: Not seeing the word "phase" anywhere actually
   Kevin: Don't think the word is exposed in the WA1 api, but it's used
          pervasively in the spec
   fantasai: Okay so that's changeable if we need it, or we can just use thee
             same name for both if we need to
   fantasai: Suggest we run with phase, we can change it if we have
             something better
   <TabAtkins> +1
   [wrapping up]

Received on Saturday, 18 June 2022 06:16:45 UTC