Using querySelectorAll to retrieve direct children Using querySelectorAll to retrieve direct children javascript javascript

Using querySelectorAll to retrieve direct children


Good question. At the time it was asked, a universally-implemented way to do "combinator rooted queries" (as John Resig called them) did not exist.

Now the :scope pseudo-class has been introduced. It is not supported on [pre-Chrominum] versions of Edge or IE, but has been supported by Safari for a few years already. Using that, your code could become:

let myDiv = getElementById("myDiv");myDiv.querySelectorAll(":scope > .foo");

Note that in some cases you can also skip .querySelectorAll and use other good old-fashioned DOM API features. For example, instead of myDiv.querySelectorAll(":scope > *") you could just write myDiv.children, for example.

Otherwise if you can't yet rely on :scope, I can't think of another way to handle your situation without adding more custom filter logic (e.g. find myDiv.getElementsByClassName("foo") whose .parentNode === myDiv), and obviously not ideal if you're trying to support one code path that really just wants to take an arbitrary selector string as input and a list of matches as output! But if like me you ended up asking this question simply because you got stuck thinking "all you had was a hammer" don't forget there are a variety of other tools the DOM offers too.


Does anyone know how to write a selector which gets just the direct children of the element that the selector is running on?

The correct way to write a selector that is "rooted" to the current element is to use :scope.

var myDiv = getElementById("myDiv");var fooEls = myDiv.querySelectorAll(":scope > .foo");

However, browser support is limited and you'll need a shim if you want to use it. I built scopedQuerySelectorShim for this purpose.


Here's a flexible method, written in vanilla JS, that allows you to run a CSS selector query over only the direct children of an element:

var count = 0;function queryChildren(element, selector) {  var id = element.id,      guid = element.id = id || 'query_children_' + count++,      attr = '#' + guid + ' > ',      selector = attr + (selector + '').replace(',', ',' + attr, 'g');  var result = element.parentNode.querySelectorAll(selector);  if (!id) element.removeAttribute('id');  return result;}