Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS Syntax design considerations and alternatives #4338

Closed
majido opened this issue Jun 5, 2019 · 5 comments
Closed

CSS Syntax design considerations and alternatives #4338

majido opened this issue Jun 5, 2019 · 5 comments
Assignees
Labels

Comments

@majido
Copy link
Contributor

majido commented Jun 5, 2019

This issue is meant to help consider alternatives and different design for scroll timeline css syntax assuming the current general working models. Note that if we drastically alter the working models of scroll-linked animations these design discussions may not apply.

Assumptions

scroll-linked animation interaction model: basically, ScrollTimeline outputs time values that directly drive a regular web Animation by setting its currentTime.

ScrollTimeline properties:

  • start, end offset
  • scroll source (single element)
  • orientation, timeRange, fill mode

Timeline Syntax

A) Timeline Property

This is the current standing syntax proposal which basically adds a new animation property that can be used to adjust each individual animations. The property takes a css function which allows various timeline props to be configures using that function parameters.

  @keyframes progress {
    from {
      width: 0vw;
    }
    to {
      width: 100vw;
    }
  }
  .progress {
    animation-name: progress;
    animation-duration: 1s;
    animation-timing-function: linear;
    /* Assume the HTML element has id 'root' */
    animation-timeline: scroll(element(#root), vertical);
  }

Pros:

  • Simple to add and understand
  • Fairly simple to implement i.e., no need to introduce a new @rule syntax.

Cons:

  • Not possible to use a single timeline instance with multiple animations (This may actually be a pro too :) )
  • Jamming all various properties of the scroll timeline into a css function seems a bit awkward.

Note that w3c/scroll-animations#25 points our that the current scroll() function syntax need revision but that is a minor change.

B) @Timeline rule

This is mostly based on the proposal in w3c/scroll-animations#48 but only limited to parts relevant to current interaction model.

@timeline root-scroller-timeline {
  timeline-type: scroll; 
  timeline-node: selector(:root) ; /* the element that controls this timeline;
         the selector would match a single element using document.querySelector() rules */
  scroll-direction: block; /* descriptors that are specific to scroll timelines */
  scroll-offset-start: 5rem;
  scroll-offset-end: calc(100% - 5rem); /* scroll-offset-end instead of end-scroll-offset
          so that we could have a scroll-offset shorthand */ 
}
@keyframes progress {
  from {
    width: 0vw;
  }
  to {
    width: 100vw;
  }
}
.progress {
   animation-name: progress;
   animation-duration: duration(root-scroller-timeline); /* maybe also use it with calc. */
   animation-timeline: root-scroller-timeline;
 }

Pros:

  • giving timeline its own name means that we can use it in multiple locations e.g., see how animation-duration is linked to the timeline duration.
  • solution here can also be used when it comes to scroll triggered animations e.g., maybe
@trigger point(root-scroller-timeline, 10%) {
  /* declare transition here */
}

Cons:

  • @birtles pointed out that "@keyframes is already quite problematic when it comes to shadow DOM etc. due to the requirement to have a globally unique name. It also makes generating @keyframes from script a pain. I wonder if we could find an alternative mechanism that allows names to be re-used somehow? Perhaps something along the lines of how counters work?"

Other relevant questions

How should the css specified timelines map to JS instances?
One approach is to create a separate timeline instance for each animation/timeline pair. This limits the each scroll-timeline to be assigned to a single animation which keeps things simple avoiding potential complications such as w3c/scroll-animations#35 but it may be counter intuitive specially for the rule-based syntax. (Note that ScrollTimelines are fairly cheap to create)

The other is to treat each declaration as an instance and then use that instance for all animations that match

Do we need a special syntax to identify the viewport scroller?
This is specially important for scroll-linked effects inside iframes that want to reference "viewport".

Scroll Source Element Selector

The current proposals assumes the following construct that helps select the source of scroll timeline in CSS:

element(<id-selector>) or selector(<selector-list>

The rough desired behavior is that the selector would match a single element using either getElementById() or document.querySelector() rules. But AFAICT this is the first time in css we allow such a construct (e.g., a selectors inside the css declaration) so it is worth making sure it is safe and efficient.

Some other questions that we need to answer:

  • is this live? i.e., if dom elements are added to the page so that querySelector would return a new element will we switch the source. I think it should be given that we need this semantic at least for the first assignment but do we allow re-assignment

  • which one? why limit to element id selectors when we can potentially allow any selector as long as we apply the querySelector semantic on top

  • Implementation wise, is this something that can be done in existing style engines?

If these type of element selector is undesirable and alternative may be to do something like "allow scroll source to be the nearest ancestor scroller with a given name or attribute". This is more limited but maybe this is good enough?!

@majido
Copy link
Contributor Author

majido commented Jun 6, 2019

It was pointed out to me that we may already have the need for tracking ids for other purpose so perhaps element(<id-selector>) is easier to implement than a general selector(<selector-list>). It may also be more appropriate since scroll source can only be a single element.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Jun 6, 2019

But AFAICT this is the first time in css we allow such a construct (e.g., a selectors inside the css declaration) so it is worth making sure it is safe and efficient.

There are other uses in CSS that do this, but they are not widely implemented in browsers. There is an element(id) image function that generates an image that is a picture of the other element's current rendering. It is implemented in Firefox. There is also an unrelated element() function in the Generated Content for Paged Media module. I'm a little uncomfortable with overloading that name further, but I in general have no problem with matching only by id — so long as we handle naming scope issues and shadow DOM. (Which is a general problem that needs to be solved for all of CSS.)

But, your concerns are definitely valid. Any sort of cross-reference between two elements is going to have complications. The nearest ancestor scroller is simpler, but limits the use cases.

@tabatkins
Copy link
Member

@birtles pointed out that "@Keyframes is already quite problematic when it comes to shadow DOM etc. due to the requirement to have a globally unique name. It also makes generating @Keyframes from script a pain. I wonder if we could find an alternative mechanism that allows names to be re-used somehow? Perhaps something along the lines of how counters work?"

Note that this is a generic problem, and I have a generic solution in #1995 that appears to have reasonable consensus. Assuming this is what we go with, then the @timeline name isn't a problem.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed design considerations for the syntax of scroll animations.

The full IRC log of that discussion <emilio> topic: design considerations for the syntax of scroll animations
<AmeliaBR> s/are coming with/for Adam are:/
<astearns> github: https://github.com/WICG/scroll-animations/issues/49
<emilio> github: https://github.com/WICG/scroll-animations/issues/49
<argyle> thx all
<emilio> majidvp: there's two issues I want to discuss, mostly about syntax
<emilio> ... second is a higher-level discussion
<AmeliaBR> s/mostly/first is mostly/
<AmeliaBR> Scroll animations proposal: https://wicg.github.io/scroll-animations/
<emilio> ... just as a reminder, scroll-timeline has been incubated in WYCG and the basic idea is that you take a scroll offset and map it to time values so that you can animate the scroll
<emilio> ... initially the proposal had CSS syntax
<emilio> ... and I wanted to focus on that since we've been mostly focused on the JS API
<emilio> ... there's two main ways you can go about scroll-timeline
<emilio> ... the first one is having a property (animation-timeline)
<emilio> ... AmeliaBR brought up an issue / alternative design, rather than making animation-timeline being a property, you'd have an `@timeline` rule
<emilio> ... on which you can describe the values, similar to `@keyframes`
<emilio> ... this is the first issue that I wanted to bring up, birtles mentioned that `@keyframes` had weird interactions with Shadow DOM for example
<emilio> ... I think `@timeline` is interesting
<emilio> ... allow more expressive syntax, and reusing the timeline for multiple elements
<emilio> ... so I personally like it
<emilio> ... but I wanted more feedback
<emilio> dbaron: Is there an example that shows this proposal?
<emilio> astearns: first comment in #49
<emilio> AmeliaBR: note that both proposals allow extending to other non-scroll timelines
<emilio> ... like video play-time position, or some subset of scrolling
<emilio> ... either syntax needs to be extensible
<emilio> ... my concerns with stashing the whole definition into a property is (1) has too much information, specially if we extend it, and (2) makes it less obvious how to trigger multiple animations to the same thing with adjustments
<emilio> ... lastly (and this is the second issue), it doesn't have a way to talk about the duration and delay using different timeline approachss
<emilio> ... so for example you tell that your scroll range is 10s, and your animation is 3s and starts at the 5th seconds, etc
<emilio> ... which is very unintuitive, so decoupling it a bit would be nice
<heycam> emilio: this changes the meaning of the animation properties
<heycam> ... the example in the first comment
<heycam> ... you define an animation from 0 to 100, to the whole viewport
<heycam> ... and if you run it in a browser that doesn't support this property, that shows the whole element
<heycam> ... how does that interact with the new property?
<heycam> majidvp: I'm not sure I fully understand. the keyframes are the same depending on whether you link the animations to time or to scroll. the only new thing we're adding is the animation timeline
<heycam> astearns: the keyframe rule in the first example, for a browser that doesn't support scroll animations, is not going to work
<heycam> AmeliaBR: in this case it won't do anything, since you're not setting a valid animation-duration
<heycam> ... you could set a fallback duration that is a time duration
<heycam> emilio: in the first example
<heycam> ... if you have a .progress element, the first thing the UA does is animte that
<heycam> AmeliaBR: yes you'd need to use some @supports to
<heycam> ... you're using time values, and an extra property that means oh actually they're not time values they're scroll values
<heycam> ... in the second version, then we're setting animation-duration to a function that would be invalid in an existing impl
<heycam> astearns: so for you the second one would be preferable
<heycam> emilio: probably? haven't thought through all the implications
<heycam> majidvp: one of the things I like about the second proposal is that you can avoid mapping everything ot time
<heycam> ... you can specify it in terms of the duration of the scroll timeline
<heycam> ... instead of manually trying to map it
<emilio> astearns: so with @timeline you can reuse it for several element but you have to reuse all the other animation properties
<emilio> AmeliaBR: that's also true of the other proposal
<emilio> majidvp: I think the feedback that emilio was good
<emilio> majidvp: and seems like adding another @-rule is not problematic so that's great
<emilio> ... so I'll try to come with a more refined proposal
<emilio> ... now, the second issue
<emilio> ... you need to specify what's the scroll source for your timeline
<emilio> ... the first one has `element(#<id>)`
<emilio> ... the second one has `selector(<selector>)`
<emilio> ... I don't know if this is something that has been in CSS before
<emilio> ... so I don't know if a function operating on an element id is something better and what are the corner cases
<emilio> TabAtkins: we've definitely done ids
<emilio> ... there's two existing element id functions, but not all of them are wildly implemented
<emilio> ... `-moz-element()` and there's something as well in paged media
<emilio> TabAtkins: there's also the nav properties, but aren't implemented in any browser
<emilio> hober: I think presto had it implemented
<emilio> emilio: there's also all the ids in urls and such
<emilio> TabAtkins: so there's a number of examples of using an id
<emilio> ... and they're all live
<emilio> ... we don't have any specific usage for an id, but syntax-wise I'd rather not add a new `element()` function
<emilio> flackr: we could also automatically select the nearest scrollable ancestor but it does limit the use-cases
<emilio> AmeliaBR: that does limit the use cases, you'd need to move stuff out of the scroller using position: fixed and such
<emilio> astearns: we could add v1 with auto-selection, and v2 with a way of selecting arbitrary elements
<heycam> emilio: regarding selectors, people had added ways to do random stuff with selectors in Shadow DOM v0, it ended up being not great
<heycam> ... since they're not terribly fast
<heycam> ... so if an ID is workable, that would be better
<emilio> majidvp: so it seems like id selection seems to address all use-cases, and we could fall back to auto-scrollable selector
<emilio> AmeliaBR: we could use the `selector` function with a hash so that we could extend it
<emilio> ... and one final point, need to be careful with shadow DOM and such
<emilio> emilio: that'd be an issue for selectors as well
<emilio> majidvp: ok, so next topic

@dontcallmedom dontcallmedom transferred this issue from WICG/scroll-animations Sep 19, 2019
@majido majido added the scroll-animations-1 Current Work label Sep 19, 2019
@majido majido self-assigned this Mar 31, 2020
@majido majido added this to the scroll-animations-1 FPWD milestone Mar 31, 2020
majido added a commit that referenced this issue Apr 3, 2020
…4338, #4336) (#4751)

## Introduce @timeline at-rule

Allow animation-name property to be used to select timeline
Update examples to use new syntax

## Use shorted names for properties:
 startScrollOffset => start
 endScrollOffset   => end
 scrollSource      => source

## Minor changes to avoid bikeshed WARNING:
 - disambiguate reference to rAF
 - Reference layout cycle
@majido
Copy link
Contributor Author

majido commented Apr 23, 2020

This specification has been updated per earlier resolution. Marking this as fixed.

@majido majido closed this as completed Apr 23, 2020
JTensai pushed a commit to JTensai/csswg-drafts that referenced this issue May 13, 2020
…3c#4338, w3c#4336) (w3c#4751)

## Introduce @timeline at-rule

Allow animation-name property to be used to select timeline
Update examples to use new syntax

## Use shorted names for properties:
 startScrollOffset => start
 endScrollOffset   => end
 scrollSource      => source

## Minor changes to avoid bikeshed WARNING:
 - disambiguate reference to rAF
 - Reference layout cycle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants