Skip to content

[css-animations-2] [web-animations-2] Animation trigger event #12314

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

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 59 additions & 4 deletions css-animations-2/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -962,14 +962,67 @@ The values of 'animation-trigger-exit-range-start' have the following meaning:
it defaults to 100%.
</dl>

## The 'trigger-name' property ## {#trigger-name}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this property should be moved to a separate section since it's not a sub-property of animation-trigger.


The 'trigger-name' property causes an [=event-based animation trigger=] to be created
for any animation whose target element has an 'animation-trigger-event' property
with matching <<trigger-name>>.
When an {{Event}} is dispatched with the element having the matching 'trigger-name' property
as {{Event/target}},
and with {{Event/type}} matching the <<trigger-event-type>> of the
'animation-trigger-event' property on the animation target, the animation's
playback is modified according to its
'animation-trigger-behavior' property, as described for
[=event-based animation triggers=].

<pre class='propdef'>
Name: trigger-name
Value: none | [ <<trigger-name>> ]#
Copy link
Contributor

@ydaniv ydaniv Jul 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this property has no other sub-properties, why does it need to be a list?
IIUC this should simply be none | <<dashed-ident>>

Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: as specified
Animation type: not animatable
</pre>

<pre class=prod><dfn>&lt;trigger-name></dfn> = <<dashed-ident>></pre>

## The 'animation-trigger-event' property ## {#animation-trigger-event}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be moved up to sit among the other animation-trigger-* sub-properties?


The 'animation-trigger-event' property is used to specify the criteria
for [=qualifying events=] that cause an [=event-based animation trigger=]
Comment on lines +993 to +994
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be the other way around? As in, the event source should declare the types that emit its name, and the event targets should register to the name alone?
This is normally how you would register an event. You add a handler per type, and then these handlers can publish the name to trigger behavior.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give an example of the syntax you have in mind? It's not clear to me how to express the following using your suggestion:

#event-target {
  trigger-name: --my-trigger;
}
#some-other-event-target {
  trigger-name: --my-trigger;
}
#animatable {
  animation-trigger-name: --my-trigger;
  animation-trigger-event: click;
}
#some-other-animatable {
  animation-trigger-name: --my-trigger;
  animation-trigger-event: keydown;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all, this example is rather confusing to me. Did you intentionally used an example with two identical names? Are they supposed to collide? Or to be aggregated?

So to simplify with 2 different names, I was thinking on something like:

#event-target {
  trigger-event: --my-trigger click;
}
#some-other-event-target {
  trigger-event: --my-other-trigger keydown;
}
#animatable {
  animation-trigger: repeat event(--my-other-trigger);
}
#some-other-animatable {
  animation-trigger: --my-other-trigger;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think your proposed syntax is isomorphic to mine, but your syntax occupies more of the --dashed-ident namespace, because it refers to an (event type, event target) pair rather than just an event target; and because it seems to require uniqueness of --dashed-ident labels for triggers -- that's why I deliberately created an example with two identical names. The idea here is that there may be multiple event targets that all affect a single animation target. Here's a comparison of the two syntaxes:

#event-target-1 {
  trigger-name: --my-trigger;
}
#event-target-2 {
  trigger-name: --my-trigger;
}
#animatable {
  animation-trigger: event(click --my-trigger);
}

-or-

#event-target-1 {
  trigger-name: --my-trigger-1 click;
}
#event-target-2 {
  trigger-name: --my-trigger-2 click;
}
#animatable {
  animation-trigger: event(--my-trigger-1), event(--my-trigger-2);
}

Now suppose that we want either a click or a keypress to either of the event targets to trigger the animation:

#event-target-1 {
  trigger-name: --my-trigger;
}
#event-target-2 {
  trigger-name: --my-trigger;
}
#animatable {
  animation-trigger: event(click --my-trigger), event(keypress --my-trigger);
}

-or-

#event-target-1 {
  trigger-name: --my-click-trigger-1 click, --my-keypress-trigger-1 keypress;
}
#event-target-2 {
  trigger-name: --my-click-trigger-2 click, --my-keypress-trigger-2 keypress;
}
#animatable {
  animation-trigger: event(--my-click-trigger-1), event(--my-keypress-trigger-1), event(--my-click-trigger-2), event(--my-keypress-trigger-2);
}

Again, I think these syntaxes are isomorphic. My own preference to avoid --dashed-ident namespace pollution by allowing non-unique identifiers and pushing the event type specification into the animation target's style, but I don't have my heart set on it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, your idea for allowing multiple event targets to trip the same trigger (not animation) is quite interesting, but I can't think right now on anything that works that way, so it seems quite confusing. In most cases I can think of idents override each other, and are not aggregated, but I could be missing something.
I understand now your logic about reducing the amount of surface pollution in the namespace, but still it feels a bit inverted.
I Would be happy to hear more from the group on both.

Regarding the syntax you used in the examples above, since animation, and its sub-properties, are coordinated lists, delimiting the triggers above by commas makes them act on separate animations, not on the same animation. So this would be invalid.

to perform its effect on its associated [=animation=]. It consists of two parts:
a <<trigger-event-type>> that is matched against the {{Event/type}} of a dispatched {{Event}},
and an <<trigger-name>> that is matched against the 'trigger-name' property
of the event's {{Event/target}}. If both criteria match for a given event
the trigger will perform its effect on its associated [=animation=].

If the <<trigger-name>> is omitted from <<single-event-trigger>> declaration,
{{Event/target}} is matched against the element
having the 'animation-trigger-event' property itself.
Comment on lines +1001 to +1003
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's interesting! So the form of an anonymous event target would be something like event(<trigger-event-type>)?


<pre class='propdef'>
Name: animation-trigger-event
Value: none | [ <<single-event-trigger>> ]#
Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: as specified
Animation type: not animatable
</pre>

<pre class=prod><dfn>&lt;single-event-trigger></dfn> = event ( <<trigger-event-type>> <<trigger-name>>? )</pre>
<pre class=prod><dfn>&lt;trigger-event-type></dfn> = <<custom-ident>></pre>

## The 'animation-trigger' property ## {#animation-trigger}

The 'animation-trigger' property is a [=shorthand property|shorthand=]
that sets 'animation-trigger-behavior', 'animation-trigger-timeline',
'animation-trigger-range-start', 'animation-trigger-range-end',
'animation-trigger-event', 'animation-trigger-range-start', 'animation-trigger-range-end',
'animation-trigger-exit-range-start', and 'animation-trigger-exit-range-end'
together in a single declaration,
specifying the [=animation trigger=] for an animation.
together in a single declaration, specifying the [=animation trigger=] for an animation.

<pre class='propdef'>
Name: animation-trigger
Expand All @@ -984,7 +1037,9 @@ Animation Type: not animatable
</pre>

<pre class=prod>
<dfn>&lt;single-animation-trigger></dfn> = <<single-animation-trigger-behavior>> || [ none | auto | [ [ <<dashed-ident>> | <<scroll()>> | <<view()>> ] [ normal | <<length-percentage>> | <<timeline-range-name>> <<length-percentage>>? ]{0,4} ] ]
<dfn>&lt;single-animation-trigger></dfn> = <<single-animation-trigger-behavior>> || [ <<single-event-trigger>> | <<single-timeline-trigger>> ]

<dfn>&lt;single-timeline-trigger></dfn> = none | auto | [ <<dashed-ident>> | <<scroll()>> | <<view()>> ] [ normal | <<length-percentage>> | <<timeline-range-name>> <<length-percentage>>? ]{0,4}
</pre>

# Animation Events # {#events}
Expand Down
Loading