Skip to content

How to handle addEventListener on CSSPseudoElement? #12163

Open
@danielsakhapov

Description

@danielsakhapov

Full context: https://github.com/danielsakhapov/CSSPseudoElementDoc?tab=readme-ov-file#41-addeventlistener-on-a-proxyhandle

Description:
Given that the CSSPseudoElement object acts as a persistent handle, attaching an event listener via addEventListener raises further questions.

  • What does it mean to listen for an event on a handle when the actual pseudo element might not be currently rendered (e.g., due to display: none)?
  • Should the listener only become active when the pseudo element is actually rendered?
  • How does this interact with the retargeting behavior?
  • If event.target remains the Element, how does a listener on the CSSPseudoElement get invoked?
  • Does it require a special dispatch phase?

This would require some heavy discussions, as it’s already known that authors want to be able to count clicks on ::scroll-marker pseudo elements for analytics purposes.

Potential solutions on example of ::scroll-marker:

  • No direct listening on pseudo element (Status Quo):
    • Description: Do not allow addEventListener('click',...) directly on the CSSPseudoElement for ::scroll-marker. Clicks physically hitting the marker would continue to dispatch with event.target set to the originating Element. Developers would have to attach the listener to the Element and use coordinate-based hit-testing within that listener to infer if the click landed on the marker area.
    • Pros:
      • Requires no changes to the event dispatch model.
      • Zero web compatibility risk regarding event.target.
    • Cons:
      • Very poor developer ergonomics for this specific use case. Calculating marker positions and sizes to perform manual hit-testing is complex, brittle (breaks with style changes), and potentially slow.
      • Makes the CSSPseudoElement object less useful and doesn't leverage its EventTarget inheritance.
  • Allow direct listening with special dispatch phase:
    • Description: Allow developers to call scrollMarkerPseudoElement.addEventListener('click', counterFunction). When a click physically occurs on the scroll marker:
      • Special Phase: The browser's event system identifies the hit target as the ::scroll-marker and invokes counterFunction (and any other listeners attached directly to this specific CSSPseudoElement handle).
      • Standard Phase: The event dispatch continues as normal, but crucially, event.target is set to the originating scrollable Element. The event then proceeds through the capture and bubble phases relative to the Element, without re-invoking counterFunction during this standard flow.
    • Pros:
      • Directly addresses the developer need: allows attaching listeners specifically to the pseudo-element of interest.
      • Preserves web compatibility by ensuring event.target remains the Element during the standard, observable event flow.
      • Provides a meaningful use for the EventTarget inheritance on CSSPseudoElement.
      • Much better developer ergonomics than manual coordinate checking.
    • Cons:
      • Requires implementing the modified event dispatch logic (the "special phase").
      • The event model becomes slightly more complex internally, though the developer-facing API (addEventListener on the pseudo) is intuitive.
  • Introduce a new specific event type:
    • Description: Instead of using the standard click event, define a new event type like pseudoElementClick that only fires on the CSSPseudoElement handle for pseudo elements. Standard click events would continue to target the Element only.
    • Pros:
      • Avoids any ambiguity or modification related to the standard click event dispatch.
      • Clearly separates the interaction.
    • Cons:
      • Introduces a new event type for a very specific interaction, potentially leading to event type proliferation.
      • Developers might intuitively try to listen for click first and be confused why it doesn't work directly on the pseudo-element handle without the special dispatch phase.
      • Doesn't fully resolve the general question of how other standard events (like mouseover) should interact with pseudo-elements if direct listeners are desired.
  • Add event.pseudoElement as in KeyframeEffect for Web Animations:
    • Description: Add pseudoElement parameter as either CSSPseudoElement or string to event which will be set if the event was fired from the pseudo element. Allowing calling addEventListener on CSSPseudoElement can even be optional here.
    • Pros:
      • Avoids web compat issues.
      • Sidesteps pseudo lifetime/eventing complexity for the use case if pseudoElement is represented as string.
      • Proven feasible for Web Animations.
    • Cons:
      • Adding new API.

Recommendation:

Add event.pseudoElement as in KeyframeEffect for Web Animations.

Justification: This option provides the best balance. It directly enables the desired developer use case (listening for clicks on the scroll marker) with good ergonomics (addEventListener on the pseudo element object). Crucially, it achieves this while adhering to the non-negotiable web compatibility requirement that event.target for standard events like click must remain the originating Element.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions