Re: [csswg-drafts] How to handle addEventListener on `CSSPseudoElement`? (#12163)

> [@keithamus](https://github.com/keithamus): sure, `event.pseudoTarget` can be a string instead of a `CSSPseudoElement`, that's true, but note that there is a plan to add more functionality to the `CSSPseudoElement`, such as geometry utils to e.g. `getBoundingClientRect()`. And by obtaining `CSSPseudoElement` instead of a string authors would have much more power and control.

@danielsakhapov By adding a pseudo element interface we're introducing an entirely new level of capability for developers to reconcile with. Right now pseudo elements are effectively available for styling hooks, and have a limited capacity for anything else. This has some limitations but it establishes an effective contract for the developer: anything that emits an event will emit it from a target which is known to be in the tree (and therefore, very likely authored by the developer). If we allow them to participate in the event hierarchy, give them objects to which the developer must fetch using APIs that are new yet adjacent to the existing set (e.g. `querySelector`) then that contract is no longer upheld. What makes these elements pseudo? They're starting to sound a lot like elements. If they _are_ elements, why aren't we making them elements?

Again I'll cite `<details>` as an example - if you don't provide a `<summary>` one is provided for you. There are no APIs which allow you to get to the provided `<summary>`, because it is provided in a limited capacity. To elevate it from "pseudo element" to "element" you provide it yourself, then it is target-able via the already available mechanisms (`querySelector` et al).

> What would be the difference in the level of burden on developers in the string vs `CSSPseudoElement` case? In both cases all the developer would most likely do is addEventListener, receive the event and check `event.target` to understand e.g. `::scroll-marker` of which specific item of the carousel has been clicked.

If that's the case and they're just checking `event.target` then why worry about providing them access to the pseudo element at all? 

> So they won't care if it's a string or a `CSSPseudoElement` probably? And in that sense it won't make much difference in burden level on them?

They will care because a string is easy to compare: `event.pseudo == '::scroll-marker'`. How would a developer do this if value is a `CSSPseudoElement` object? They'd have to learn with and interact with a newly introduced API, so the condition becomes `event.pseudo == event.target.pseudo('::scroll-marker')`. One might argue "that's not much longer" but it's a lot more complex because now I need to think a lot more about what the return value of `pseudo()` is.

As an example of the additional cognitive overload, to borrow from your example code:

```js
function checkScrollMarker(handler) {
 const scrollMarker = list.pseudo('::scroll-marker');
 list.addEventListener('click', (event) => {
  if (event.pseudoTarget === scrollMarker) {
   // If the check passes, it calls the handler.
   handler(event);
  }
 });
}
```

Have I just introduced a memory leak? If my `list` element no longer becomes a CSS carousel, presumably it'll clean up `::scroll-marker` and `list.pseudo('::scroll-marker')` now returns `null`, but I have an event bound which captures a `scrollMarker` object in scope.

-- 
GitHub Notification of comment by keithamus
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/12163#issuecomment-3175071157 using your GitHub account


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

Received on Monday, 11 August 2025 14:21:17 UTC