Re: [csswg-drafts] [css-animations-2] Move scroll and event animation triggers to independent namespace (#12336)

The Houdini Task Force just discussed `[css-animations-2] Move scroll and event animation triggers to independent namespace`, and agreed to the following:

* `RESOLVED: use timeline-trigger-* and event-trigger-* separate property sets`

<details><summary>The full IRC log of that discussion</summary>
&lt;TabAtkins> DavidA: we have the animation-trigger feature for controlling animations<br>
&lt;TabAtkins> DavidA: we initially wrote the spec with timelines in mind<br>
&lt;TabAtkins> DavidA: so there was a timeline range you enter to do something to the animation, and a range that you could exit to do something else<br>
&lt;TabAtkins> DavidA: so we had trigger actions attached to those ranges<br>
&lt;TabAtkins> DavidA: in expanding the trigger idea to include event based, like clicking an element and having that start an animation<br>
&lt;TabAtkins> DavidA: conceptually, there's enough diff between these two trigger types that they'd require a different set of properties<br>
&lt;TabAtkins> DavidA: so should have separate property sets<br>
&lt;TabAtkins> DavidA: that's the main proposition from this issue<br>
&lt;TabAtkins> DavidA: so there is another competing model<br>
&lt;TabAtkins> DavidA: so with separate proeprty sets we have timeline-trigger-* and event-trigger-*<br>
&lt;flackr> (similar to the pattern of scroll-timeline and view-timeline)<br>
&lt;TabAtkins> DavidA: the other is that everything is an event. entering a timeline range is an event, exiting is as well<br>
&lt;TabAtkins> DavidA: the all-events model appears appealing, but we think there's some subtlely in the timeline concept that are properly reflected with just events<br>
&lt;TabAtkins> DavidA: so we think it's better to keep the property sets separate, to better capture different types of triggers<br>
&lt;TabAtkins> DavidA: it also simplifies some other aspects fo the syntax<br>
&lt;TabAtkins> DavidA: so proposal is to go with separate property sets<br>
&lt;TabAtkins> DavidA: timeline-trigger-* and event-trigger-*<br>
&lt;ydaniv> scribe+<br>
&lt;ydaniv> TabAtkins: I discussed this a lot with fantasai<br>
&lt;ydaniv> ... agree that this is the model to stick with<br>
&lt;ydaniv> ... the seperate property sets<br>
&lt;TabAtkins> lea: is there more complete code snippets showing them?<br>
&lt;TabAtkins> DavidA: the issue is really long now, but i have an explainer<br>
&lt;DavidA> https://github.com/explainers-by-googlers/scroll-triggered-animations/blob/main/CSS_PROPERTIES.md#event-trigger-examples<br>
&lt;ydaniv> q+<br>
&lt;TabAtkins> lea: [question about explainer, tab explained it a bit]<br>
&lt;TabAtkins> lea: are the play/pause etc predefined?<br>
&lt;TabAtkins> TabAtkins: yes<br>
&lt;TabAtkins> lea: down the line could we have other things care about the triggers?<br>
&lt;TabAtkins> ydaniv: yes<br>
&lt;TabAtkins> lea: what's the scope of these triggers?<br>
&lt;TabAtkins> TabAtkins: similar to view timelines, visible to element+children by default, can be lifted up with a -scope proeprty<br>
&lt;TabAtkins> DavidA: actually we've been thinking would be better fo rthem to be global by default, with -scope limiting them instead<br>
&lt;TabAtkins> flackr: we should talk more about making things consistent<br>
&lt;TabAtkins> ydaniv: we had some back and forth in the issue<br>
&lt;TabAtkins> ydaniv: there were concerns about mixing view-related triggers with others<br>
&lt;TabAtkins> ydaniv: assuming this is a real concern so we don't want to mix things...<br>
&lt;TabAtkins> ydaniv: and that's a motivation for separating timeline triggers from the rest of the events...<br>
&lt;TabAtkins> ydaniv: then i can accept timeline triggers being separate properties<br>
&lt;TabAtkins> ydaniv: and we can always invent new events like view-enter() in the future<br>
&lt;TabAtkins> ydaniv: but this might indeed be a safer way to start, yeah<br>
&lt;lea> q?<br>
&lt;TabAtkins> ydaniv: i added a comment an hour ago in the issue<br>
&lt;lea> q+<br>
&lt;ydaniv> https://github.com/w3c/csswg-drafts/issues/12336#issuecomment-3206045115<br>
&lt;TabAtkins> ydaniv: here, i suggested how to split up the properties between the elements, the api surface<br>
&lt;TabAtkins> ydaniv: making event-trigger a way to declare event triggers, timeline-trigger to declare timeilne triggers, then all the animation bheaviors (the action) only on animation-trigger<br>
&lt;TabAtkins> ydaniv: then animation-trigger is the name of the  trigger (or an anonymous functional trigger), with some controls for changing the action or behavior<br>
&lt;TabAtkins> ydaniv: this implies an "always" starting trigger<br>
&lt;TabAtkins> ydaniv: if you don't specify another one it'll reuse the starting trigger for exit, otherwise you can specify<br>
&lt;TabAtkins> ydaniv: also, timeline triggers have two ranges, they're not allowed in the exit trigger; if you specify them in the first they ignore what's specified for end<br>
&lt;TabAtkins> ydaniv: so you avoid mixing<br>
&lt;TabAtkins> flackr: that's not exactly the concern, i can clarify<br>
&lt;TabAtkins> flackr: if viewenter and viewleave are discrete events, we can't ensure you've set them up correctly so you always get a viewleave before a new viewenter<br>
&lt;TabAtkins> flackr: if they're coming from a single timeilne trigger, we *can* ensure you get them in pairs<br>
&lt;TabAtkins> ydaniv: so it's important to ahve the same timleine, but diff ranges are okay<br>
&lt;bramus> scribe+<br>
&lt;ydaniv> q?<br>
&lt;ydaniv> ack ydaniv<br>
&lt;bramus> TabAtkins: say you have a large interrange for the 1st one, enter it and dtriger, and then you have  a smaller range in the middle. Would that imply you never trigger the middle?<br>
&lt;ydaniv> TabAtkins: you have 2 timeline triggers, one large and one smaller nested inside it<br>
&lt;bramus> … you have two ranges, a small one nested inside a larger one<br>
&lt;TabAtkins> TabAtkins: would you never trigger the inner one, since you're already in the outer?<br>
&lt;TabAtkins> flackr: no, those are indepdnent. the concern is that if you have a small enter range and a large exit, you could enter the enter range, leave it, then reenter before leaving the exit range, and pure events would fire a second enter; we want to avoid that<br>
&lt;TabAtkins> TabAtkins: makes sense<br>
&lt;TabAtkins> szager: my interpretation of ydaniv's proposal was the internal mechanism would have this infomration; the events were independent in the syntax but could still be linked to only fire in the correct order<br>
&lt;TabAtkins> szager: i think it's not correct then, to say we can't guarantee against two enters in a row. it would just be a little bit magical, maybe less intuitive to devs.<br>
&lt;TabAtkins> szager: would involve a bit of hidden state<br>
&lt;TabAtkins> szager: so my objection is this hidden bit of state would be easy to get wrong for devs, maybe confusing. better to force them to be more explicit about the ranges<br>
&lt;TabAtkins> flackr: dunno if i completely agree. for simple cases could just work.<br>
&lt;TabAtkins> flackr: but say you have an enter range on a and an exit on b, another has enter on a and exit on c...<br>
&lt;TabAtkins> szager: i see, so if you're mixing timelines...<br>
&lt;TabAtkins> flackr: there's no association fo the trigger timelines, so that's an issue<br>
&lt;TabAtkins> szager: so for mixed multi-timeline case, the event model can't guarantee consistency<br>
&lt;TabAtkins> q?<br>
&lt;TabAtkins> lea: this seems great overall<br>
&lt;TabAtkins> lea: on this specific design, have we considered having just a single event trigger and making timelines a kind of event?<br>
&lt;TabAtkins> TabAtkins: that's what we were just discussing ^_^<br>
&lt;TabAtkins> flackr: say your animation start on a small view range, and only resets when it fully leaves the viewport<br>
&lt;TabAtkins> [explains this]<br>
&lt;TabAtkins> lea: can you have a shorthand to just set the exit range easily?<br>
&lt;TabAtkins> flackr: that's the default - if you don't specify an exit range, it matches the enter range automatically<br>
&lt;TabAtkins> szager: key thing is just that enter+exit have to be declared atomatically<br>
&lt;TabAtkins> *atomicly<br>
&lt;TabAtkins> lea: but if they're separate events, you could pass them both to the API...<br>
&lt;TabAtkins> szager: it's not functional that's th eproblem, it's that the enter+exit have to be tracked as a unit<br>
&lt;TabAtkins> lea: i could imagine using a click as a trigger to start an animation, then once it scrolls out you pause it, and when it comes back into the viewport...<br>
&lt;TabAtkins> ydaniv: that requires multiple triggers<br>
&lt;TabAtkins> ydaniv: which we're deferring<br>
&lt;TabAtkins> lea: what i'm concerned is we have some events that parallel some ui events, and timeline triggers that are a separate thing.<br>
&lt;TabAtkins> lea: are we likely to need more types of triggers? if so, do we want to add more sets of properties?<br>
&lt;TabAtkins> flackr: the reason for the separate namesapce is the properties for setting up the trigger depend on the type of trigger<br>
&lt;TabAtkins> flackr: events are simple - just give the name fo the event<br>
&lt;TabAtkins> flackr: for timelines, we have to supply a bunch more, like setting up an intersection observer<br>
&lt;ydaniv> TabAtkins: if we're adding more things then we add them as events<br>
&lt;ydaniv> ... if they need special cases we add more properties<br>
&lt;ydaniv> ... trying to cram all of that into a single model is not great syntactically<br>
&lt;TabAtkins> szager: coudl we talk for a moment about something from ydaniv's comment?<br>
&lt;TabAtkins> szager: specifying the actions in the animation-trigger rather than in the trigger element<br>
&lt;TabAtkins> szager: my concern here is that you have a `start exit?` which is timline-biased<br>
&lt;TabAtkins> szager: not clear ot me that an action specification like this makes sense for an event trigger<br>
&lt;TabAtkins> szager: could just say that exit is a no-op for events, but seems a little squirrelly<br>
&lt;TabAtkins> szager: so curious about what the motivation for having the action on the animation element is<br>
&lt;TabAtkins> szager: generally, the trigger element seems like the "controller" in MVC. if you were doing this in JS, you'd specify the action *in* the click handler on the trigger element, for example<br>
&lt;TabAtkins> ydaniv: a few reasons<br>
&lt;TabAtkins> ydaniv: If we want these trigger properties to be usable for other stuff later, then adding animation-related actions to those proeprties doesn't make sense<br>
&lt;TabAtkins> ydaniv: a second, say you want to name a click trigger, and you want it to play one aniamtion, reverse a different one<br>
&lt;TabAtkins> ydaniv: you'd have to declare two nearly-identical triggers<br>
&lt;TabAtkins> ydaniv: so my suggestion is that this just declares a trigger, you can use it however you want. the animation decides what to do with the event<br>
&lt;TabAtkins> szager: what about this issue of being timeline specific, with the start+exit tirggers?<br>
&lt;TabAtkins> szager: if we later wanted more options for a new type of trigger, would we have to alter this syntax? enter+exit+something else?<br>
&lt;TabAtkins> szager: looking at the third example in your comment, the exit trigger seems timeline-specific<br>
&lt;TabAtkins> ydaniv: in the case of timelines, you don't need an exit trigger. it's inherent to the timeline<br>
&lt;TabAtkins> ydaniv: but if you have an event trigger for the animation start, and you want to reverse on every click, you can just add reverse; dont' need an exit trigger<br>
&lt;TabAtkins> ydaniv: but wanted one event for starting, and another event for reversing or pausing<br>
&lt;TabAtkins> ydaniv: so in that case, start with this trigger, do the reverse/reset with another event<br>
&lt;TabAtkins> szager: a little confused aobut terminology. you said "exit", that applies just to timelines for me<br>
&lt;TabAtkins> ydaniv: exit means "end" here, start and end<br>
&lt;TabAtkins> szager: i'm confused<br>
&lt;TabAtkins> flackr: i think he just means you can specify a different event for an end trigger<br>
&lt;TabAtkins> ydaniv: so you can have click on this button to play forwards, click on another button to play backwards<br>
&lt;TabAtkins> szager: and click on a third to reset?<br>
&lt;TabAtkins> flackr: that's my concern too, there's more than two actions<br>
&lt;TabAtkins> szager: yeah, i'm concerned it'll get hairy, cramming too much into this<br>
&lt;TabAtkins> DavidA: i'm also concerned abou thow this maps to the JS api, not clear what instantiates the animation trigger<br>
&lt;TabAtkins> DavidA: right now you just have the trigger on the source element. not enough to attach the animation to it, you have to add the action as well<br>
&lt;flackr> q+<br>
&lt;TabAtkins> DavidA: becuase if you reuse the trigger you can have a different action on a different element<br>
&lt;ydaniv> TabAtkins: my concern here is that we're currently deferring the ability to add multiple triggers<br>
&lt;ydaniv> ... while timelines have the concept of 2 events mixed together, other events don't have them<br>
&lt;ydaniv> ... I think we should have just one event properly and then figure out the rest<br>
&lt;TabAtkins> flackr: i think you said pretty well what i wanted to say<br>
&lt;TabAtkins> flackr: the idea of having start+stop and making triggers independent of animations...<br>
&lt;TabAtkins> flackr: the only way I can see doing that is having basically a third thing that provides the link between an event name and an action<br>
&lt;TabAtkins> flackr: it could be that this is a functional syntax in the animation-trigger syntax<br>
&lt;TabAtkins> flackr: animatino-trigger: action(--foo play)<br>
&lt;TabAtkins> flackr: and we spec that timeline triggers generate two events, events generate all the events that are possible<br>
&lt;TabAtkins> flackr: taht's the way to go about it rathe rthan specializing timelines<br>
&lt;TabAtkins> szager: terminology point<br>
&lt;TabAtkins> szager: there are "events" from UI. timelines ahve "actions" (enter/exit). we have "behaviors".<br>
&lt;TabAtkins> szager: event is a 0-dimensional UI event, action does the thing. Timeline has two actions, enter and exit, each is linked to a behavior.<br>
&lt;TabAtkins> proposed resoluition: use timeline-trigger-* and event-trigger-* separate property sets<br>
&lt;TabAtkins> RESOLVED: use timeline-trigger-* and event-trigger-* separate property sets<br>
&lt;TabAtkins> TabAtkins: do we ahve a proposed reoslution for attaching behaviors to triggers, or take it back to the issue?<br>
&lt;TabAtkins> DavidA: can we defer for the moemnt and see if we can land on a proposal?<br>
&lt;TabAtkins> flackr: yeah, think there's three ways it could potentially work<br>
&lt;TabAtkins> DavidA: i do recognize yehonatan's concerns making the triggers animation specific, making them less reusable<br>
&lt;TabAtkins> ydaniv: if we're settling now on just using a single trigger in animation-trigger, and then a behavior, we can go back to the older syntax, a keyword for the behavior and once/repeat/always/state<br>
&lt;TabAtkins> ydaniv: i think that's something that can work both for timelines and events<br>
&lt;TabAtkins> ydaniv: by default "once"<br>
&lt;TabAtkins> ydaniv: and if we ahve a timeline, it uses the two ranges<br>
&lt;TabAtkins> szager: this ocmes back to my original attempt to cast events into the timeline behaviors, we had objections to those<br>
&lt;TabAtkins> ydaniv: i just think, in all our proposals, the default action is to play<br>
&lt;TabAtkins> ydaniv: we can split things more when we add multiple triggers to an animation. but for now, you always play first, then do something else on subsequent events<br>
&lt;flackr> scribe+<br>
&lt;flackr> TabAtkins: either need to allow multiple clicks in the action in some way or talk about multiple triggers on one animation so we can assign multiple behaviors to a given click<br>
&lt;flackr> TabAtkins: this split of once / always state felt very confusing, defined purely about actions in the animations api rather than what the author or user saw happened<br>
&lt;flackr> TabAtkins: it's possible it was just confusingly authored, but it seems more consideration needs to happen about what behavior of events are<br>
&lt;flackr> TabAtkins: Lots of ways to potentially do this. The behaviors need to be TBD for a bit<br>
&lt;TabAtkins> szager: i need to head out, but i think this needs more discussion, yes<br>
&lt;TabAtkins> flackr: i think having multiple triggers isn't controversial, it's just a question of what the splitting mechanism is<br>
&lt;TabAtkins> flackr: we already have comma-separated list coordinating with the naimation list<br>
&lt;TabAtkins> flackr: we need another delimiter, then<br>
&lt;TabAtkins> flackr: maybe spaces is sufficient and we coudl go with that<br>
&lt;TabAtkins> DavidA: a nice thing about animation-trigger just being the name, that's pretty easy<br>
&lt;TabAtkins> flackr: right, if anmatino-trigger is a shorthand for a bunch of values, that's very hard. but if it's just trigger, or trigger+behavior, we can probably do it pretty easily<br>
&lt;TabAtkins> DavidA: in JS, think of TimelineTrigger object<br>
&lt;TabAtkins> DavidA: if it's an object, maybe you can listen to its events<br>
&lt;TabAtkins> DavidA: that would still be something we can map somehow to be used outside of animation context<br>
&lt;TabAtkins> DavidA: even if we implicitly bake the actions into these, it woudln't stop us getting the signals<br>
&lt;TabAtkins> flackr: I think we can consider this issue resolved, and open a new issue about exactly how we associate beahviors<br>
</details>


-- 
GitHub Notification of comment by css-meeting-bot
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/12336#issuecomment-3206545734 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 20 August 2025 14:04:46 UTC