Re: [whatwg/dom] Add an optional options dictionary to `closest` to allow jumping across shadow boundaries (Issue #1265)

GarrettS left a comment (whatwg/dom#1265)

So you want to stop traversing at a certain point to:

1. avoid matching stuff you don't want
2. be efficient — don't traverse to root if know you should stop two hops up

Without a boundary parameter, closest() breaks encapsulation. 

Performance matters, and with a high-frequency event listener like pointermove or scroll, in a potentially infinitely deep DOM tree in an infinite scroll doc (like ChatGPT), it adds up.

Look for the element where you want it, and not where you don't.

Giving the `closest` method an `ancestor` property would be a big improvement. 

```js
target.closest('button', { ancestor: ev.currentTarget });
```
— or if the API doesn't need other options — 
```js
target.closest('button', ev.currentTarget);
```

And if you want it all the way to root, pass ownerDocument | document | window, etc.
```js
target.closest('button', ev.currentTarget.ownerDocument);
```
Stop at shadow root boundary:
```js
target.closest('button', target.getRootNode());
```


(Aside: The event.currentTarget property is the element the event listener was attached to.)

As for relevance, jquery .closest( selector [, context ] ), inspired by my 2004 findAncestorWithClass "Prior Art". I have been using similar patterns for 22+ years. There is currently no CSS selector alias for "the element that caught this event". That's the gap to fill.

:scope won't work because iut looks down, while closest looks up.

```js
const match = el.closest('button');
if (match && currentTarget.contains(match))
```
clunks and won't work in shadow dom. Look all the way up, if a match is found, look down from currentTarget. 

-- 
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/1265#issuecomment-4645753701
You are receiving this because you are subscribed to this thread.

Message ID: <whatwg/dom/issues/1265/4645753701@github.com>

Received on Monday, 8 June 2026 05:37:41 UTC