Skip to content

How to handle addEventListener on CSSPseudoElement? #12163

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
danielsakhapov opened this issue May 5, 2025 · 0 comments
Open

How to handle addEventListener on CSSPseudoElement? #12163

danielsakhapov opened this issue May 5, 2025 · 0 comments
Labels
css-pseudo-4 Current Work

Comments

@danielsakhapov
Copy link
Contributor

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.

Proposed variants are included in the table:

Model event.target Behavior (for existing events like click) addEventListener on Pseudo? Pros Cons Feasibility Notes
A: Status Quo Element (retargeted) No Full web compatibility. Simple. No direct script interaction with pseudo events. Current state.
B: Full EventTarget CSSPseudoElement Yes Direct event handling on pseudo. Conceptually clean object model. Major breaking change for web compatibility. Complex bubbling definition needed, esp. for non-tree pseudos. Highly unlikely due to web compatibility constraints.
C: Hybrid (Parent + Selector) Element (retargeted) No (Interaction via parent) Avoids web compat issues. Sidesteps pseudo lifetime/eventing complexity for the use case. Less direct object model. Requires specific API pattern (like Web Animations pseudoElement). Proven feasible for Web Animations L1. Potentially applicable to other interactions.
D: Limited EventTarget Element (for existing events). CSSPseudoElement (for new specific events only). Yes (for specific events) Maintains web compat for existing events. Allows direct handling for new use cases. Complex dispatch logic. Bubbling complexity remains for events targeting pseudo. Potential developer confusion. Requires careful definition of which events target what, and clear bubbling rules. Avoids the main breaking change of Model B.

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 scrollable 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 scrollMarkerClick that only fires on the CSSPseudoElement handle for the ::scroll-marker. 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.

Soft, but somewhat desired recommendation:

Option 2: Allow Direct Listening with Special Dispatch Phase.

Justification: This option provides the best balance. It directly enables the desired developer use case (listening for clicks on the 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. While it requires implementing a modification to the event dispatch mechanism, this internal complexity seems justified to provide a usable and compatible solution. Option 1 is too cumbersome for developers, and Option 3 introduces a new event type which might be unnecessary if the dispatch modification in Option 2 can be generalized for other standard events targeting pseudo-elements.

@danielsakhapov danielsakhapov added the css-pseudo-4 Current Work label May 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-pseudo-4 Current Work
Projects
None yet
Development

No branches or pull requests

1 participant