search ]

JavaScript querySelector vs. querySelectorAll Explained

This guide covers the querySelector() and querySelectorAll() methods – how they work, when to use each one, and how to loop through the results.

The DOM (Document Object Model) represents all HTML elements in a tree structure. Each element in that tree can be accessed using JavaScript and the browser’s built-in API. The querySelector and querySelectorAll methods are the most flexible way to select elements from the DOM because they accept any valid CSS selector.

Take a look at the following markup. We will use it for all the examples in this post:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>JavaScript DOM API querySelector and querySelectorAll Examples</title>
</head>
<body>
  <div class="wrapper">
    <div class="name">Liam</div>
    <div class="name">Noah</div>
    <div class="name">William</div>
    <div class="name">James</div>
    <div class="name">Benjamin</div>
    <div class="name">Elijah</div>
  </div>
  <div id="country">USA</div>

  <footer>Just some footer text</footer>
  <script>
    // code goes here
  </script>
</body>
</html>

querySelectorAll – Example

The syntax for querySelectorAll:

const elements = parentNode.querySelectorAll(cssSelector);

To find all div elements with the class name in the HTML structure above:

<script>
  const names = document.querySelectorAll(".name");
  console.log(names);
</script>

Line 2 returns a NodeList containing all six elements with the class name.

querySelector – Example

While querySelectorAll returns all matching elements, querySelector returns only the first match. Here is the syntax:

const element = parentNode.querySelector(cssSelector);

The querySelector method accepts any CSS selector as an argument and returns the first matching element, or null if no match is found.

<script>
   const country = document.querySelector("#country");
   console.log(country);
</script>

This returns the element with the ID country.

Example for querySelector

querySelector vs. getElementById and getElementsByClassName

You may wonder when to use querySelector over older methods like getElementById() and getElementsByClassName(). The key difference is that querySelector and querySelectorAll accept any CSS selector, making them far more flexible. You can use complex selectors like div.wrapper > .name:first-child or [data-role="close"].

However, getElementById() is faster because it uses the browser’s internal ID lookup table directly. In benchmarks, it runs roughly 2x faster than querySelector(). For simple ID lookups in performance-critical code, getElementById() is the better choice.

There is one important difference between the results these methods return. querySelectorAll() returns a static NodeList – a snapshot of the DOM at the time of the query. Methods like getElementsByClassName() return a live HTMLCollection that updates automatically when the DOM changes. Keep this in mind when your code modifies the DOM while iterating over the results.

Looping through a NodeList with forEach

The querySelectorAll method returns a NodeList, which supports the forEach() method in all modern browsers (Chrome 51+, Firefox 50+, Safari 10+, Edge 16+):

const names = document.querySelectorAll(".name");
names.forEach((element) => {
  console.log(element);
});

You can also use a for...of loop, which works the same way and has equally broad support:

const names = document.querySelectorAll(".name");
for (const element of names) {
  element.style.color = "blue";
}

If you need array methods like map(), filter(), or reduce() on the results, spread the NodeList into an array first: [...document.querySelectorAll(".name")].

Scoping querySelector to a Parent Element

Both querySelector and querySelectorAll can be called on any element, not just document. This scopes the search to that element’s descendants, which is useful for working with components or sections of a page:

const wrapper = document.querySelector(".wrapper");
const firstChild = wrapper.querySelector(".name");
console.log(firstChild.textContent); // "Liam"

FAQs

Common questions about querySelector and querySelectorAll:

What is the difference between querySelector and querySelectorAll?
querySelector() returns the first element that matches a CSS selector, or null if no match is found. querySelectorAll() returns a static NodeList of all matching elements, or an empty NodeList if there are no matches. Use querySelector() when you need one element and querySelectorAll() when you need all of them.
Is querySelector slower than getElementById?
Yes. getElementById() is roughly 2x faster because browsers maintain an internal ID lookup table that allows direct access. querySelector() uses a CSS selector engine, which adds parsing overhead. In practice, the difference is negligible for most applications, but for performance-critical loops, getElementById() is the better choice for simple ID lookups.
Does querySelectorAll return a live or static NodeList?
querySelectorAll() returns a static NodeList - a snapshot of the DOM at the time of the call. If the DOM changes afterward, the NodeList does not update. This is different from getElementsByClassName() and getElementsByTagName(), which return live HTMLCollections that reflect DOM changes automatically.
Can I use querySelector on a specific element instead of document?
Yes. Both querySelector() and querySelectorAll() are available on any DOM element, not just document. Calling them on a specific element scopes the search to that element's descendants. For example, wrapper.querySelector(".item") only searches inside the wrapper element.
What happens if querySelector finds no matching element?
querySelector() returns null when no element matches the selector. querySelectorAll() returns an empty NodeList (with a length of 0). Always check the result of querySelector() for null before accessing properties on it, or you will get a TypeError.

Summary

querySelector() returns the first matching element, while querySelectorAll() returns a static NodeList of all matches. Both accept any CSS selector, making them more flexible than getElementById() or getElementsByClassName(), though the older methods are faster for simple lookups. You can loop through a NodeList using forEach() or for...of in all modern browsers, and scope your queries to a specific parent element to narrow the search.

Here are related posts on the topic:

Join the Discussion
0 Comments  ]

Leave a Comment

To add code, use the buttons below. For instance, click the PHP button to insert PHP code within the shortcode. If you notice any typos, please let us know!

Savvy WordPress Development official logo