Using :scope To Identify The Host Element In .querySelectorAll()
Here's a helpful tip that I learned the other day. When using a Document Object Model (DOM) method to query for HTML elements using a CSS selector (ex, .querySelectorAll()
), the :scope
pseudo-class can be used to identify the host element on which the method is being called. This allows us to use the direct descendant selector (>
) to target children of the host element.
Run this demo in my JavaScript Demos project on GitHub.
View this code in my JavaScript Demos project on GitHub.
Consider this HTML snippet:
<p> | |
<span> <em>1</em> </span> | |
<span> <em>2</em> </span> | |
<span> <em>3</em> </span> | |
<span> <em>4</em> </span> | |
<span> <em>5</em> </span> | |
<span> <em>6</em> </span> | |
<span> <em>7</em> </span> | |
<span> <em>8</em> </span> | |
<span> <em>9</em> </span> | |
<span> <em>10</em> </span> | |
</p> |
If we wanted to query the p
element for "odd children", how would we do it? My first instinct was to try and call:
.querySelectorAll( " > :nth-child(odd) " )
Unfortunately, this isn't a valid CSS selector since there's nothing anchoring the direct descendant (>
) selector. So, we might try to anchor it to *
:
.querySelectorAll( " * > :nth-child(odd) " )
This runs without error; but, it doesn't do what we want. In the above snippet, it ends up selecting every distant descendant <em>
element since each of them is the first (odd) child within a <span>
.
The solution is to use the :scope
pseudo-class. This represents the element on which the .querySelectorAll()
method is being called:
.querySelectorAll( " :scope > :nth-child(odd) " )
To see this in action, I've created a demo that uses this selector and applies a background-color to the targeted nodes:
<!doctype html> | |
<html lang="en"> | |
<body> | |
<p onclick="selectOdds( event )"> | |
<span> <em>1</em> </span> | |
<span> <em>2</em> </span> | |
<span> <em>3</em> </span> | |
<span> <em>4</em> </span> | |
<span> <em>5</em> </span> | |
<span> <em>6</em> </span> | |
<span> <em>7</em> </span> | |
<span> <em>8</em> </span> | |
<span> <em>9</em> </span> | |
<span> <em>10</em> </span> | |
</p> | |
<script type="text/javascript"> | |
function selectOdds( event ) { | |
var targets = event | |
.currentTarget | |
// In the selector, ":scope" represents the current element on which the | |
// query is being called. This allows us to use the direct-descendant | |
// operator since it gives us a way to identify the parent of the direct | |
// descendants. | |
.querySelectorAll( ":scope > :nth-child( odd )" ) | |
; | |
for ( var node of targets ) { | |
node.style = "background-color: hotpink ; color: white ;"; | |
} | |
} | |
</script> | |
</body> | |
</html> |
If I click on the <p>
tag and execute the onclick
handler, we locate the odd direct-descendants and highlight them in hawt pink:

As you can see, each of the odd direct-descendants of the host element were highlighted in hot pink.
The :scope
pseudo-class, which I hadn't heard of until a few days ago, has been widely supported for many years. The last browser to add support for it was Edge back in 2019.
Want to use code from this post? Check out the license.
Reader Comments
So cool. CSS is pure magic 🪄✨
@Chris,
CSS is indeed pretty power, when it does what you want 😜
I've really enjoyed using querySelector and querySelectorAll. I got tired of typing out though so I typically create a function to handle the calls:
Always something to learn.
@Hugh,
I love the idea of the short-hand methods. This is one of my biggest sentimental misses from the jQuery days. It's just hard to ever feel like anything is easier / better than
$()
😄 Even in HTMX - the framework that I'm learning right now - has it's ownhtmx.find()
method internally, that does something very similar to what you've done as well.Post A Comment — ❤️ I'd Love To Hear From You! ❤️