# querySelector or querySelectorAll: which one should I use?

Source: https://coursesweb.net/forum/t/queryselector-or-queryselectorall-which-one-should-i-use/
Site: CoursesWeb Forum, category JavaScript and the DOM
Published: 2026-11-13. Updated: 2026-11-13. Replies: 0.

## Question by Teodora Vance (staff), 2026-11-13

Use querySelector when you need one element: it returns the first match, or null if there is none. Use querySelectorAll when you need every match: it returns a list, which is empty rather than null when nothing matches. Both accept any CSS selector, so choose by how many elements you want to work with.

## A minimal working example

Here is a small menu. We want to find the menu itself (one element) and every item in it (many elements):

```html
<ul id="menu">
  <li class="item">Home</li>
  <li class="item">Docs</li>
  <li class="item">Contact</li>
</ul>
```

```js
const menu = document.querySelector("#menu");
const firstItem = document.querySelector(".item");
const items = document.querySelectorAll(".item");

console.log(firstItem.textContent); // "Home"
console.log(items.length);          // 3

items.forEach((item) => {
  item.addEventListener("click", () => {
    items.forEach((other) => other.classList.remove("active"));
    item.classList.add("active");
  });
});
```

`querySelector` gives you one element, so you can use it directly. `querySelectorAll` gives you a list, so you loop over it and act on each element. The script needs to run after the HTML exists, so load it with `defer` as described in [why getElementById returns null](/forum/t/why-does-getelementbyid-return-null-and-break-innerhtml-in-my-script/).

## Why they behave this way

MDN's [querySelector page](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) says the method returns the first element that matches the selector, or `null` if there are no matches. MDN's [querySelectorAll page](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll) says it returns a static (not live) `NodeList` of the matching elements, or an empty list if nothing matches, in document order.

A `NodeList` is a list-like object holding elements. "Static" means it is a snapshot taken at the moment you call it. If you add another `li` later, the list you already have does not grow. Run the query again to get a fresh one.

The selector is the same CSS selector you use in a stylesheet. A dot means class, a hash means id, and a bare word means tag name. Selectors can be combined: MDN's example `div.note, div.alert` finds every div with either class.

You can also search inside one element instead of the whole page. This only looks inside `menu`:

```js
const links = menu.querySelectorAll("a");
```

## Which one to pick

| You want | Use | If nothing matches |
| --- | --- | --- |
| One element that has an id | `getElementById("menu")` or `querySelector("#menu")` | `null` |
| The first element matching a selector | `querySelector(".item")` | `null` |
| Every element matching a selector | `querySelectorAll(".item")` | An empty list |

Our tutorial on [querySelector and querySelectorAll](https://coursesweb.net/javascript/queryselector-queryselectorall) shows more selector patterns.

## A safe pattern for one element

Because `querySelector` can return `null`, check before you use the result. This also keeps the rest of your script running when a page does not contain that element:

```js
const banner = document.querySelector(".banner");

if (banner) {
  banner.textContent = "Welcome back";
}
```

With `querySelectorAll` you do not need that check. An empty list loops zero times, so the `forEach` does nothing. That is one reason many people reach for it when an element is optional.

## Mistakes beginners make

1. **Using the list like an element.** `document.querySelectorAll(".item").addEventListener(...)` fails with an error saying `addEventListener` is not a function, because a list is not an element. Loop with `forEach`, or write `[0]` if you only want the first.
2. **Forgetting the dot or the hash.** `querySelector("item")` looks for a tag named `item`, not a class. Write `".item"` for a class and `"#menu"` for an id.
3. **Not handling null.** If `querySelector` finds nothing and you write `el.textContent`, you get a TypeError. Check with `if (el)` first.
4. **Writing an invalid selector.** MDN says a selector that is not valid CSS throws a `SyntaxError`. An id like `this?element` has to be escaped with `CSS.escape()` before you use it in a selector.
5. **Expecting the list to update.** The list from `querySelectorAll` is a snapshot. Query again after the page changes.

## Check this in order

1. In the console, run `console.log(document.querySelectorAll(".item"))`. Do you see a list with the right number of elements?
2. Copy the same selector into the Elements panel search box (Ctrl+F or Cmd+F). It finds the same matches.
3. Check the prefix. Dot for class, hash for id, nothing for a tag.
4. Check that the script runs after the elements exist.
5. Check which variable holds a list and which holds one element. Name them to match, like `item` and `items`.

---
Cite as: CoursesWeb Forum, "querySelector or querySelectorAll: which one should I use?", https://coursesweb.net/forum/t/queryselector-or-queryselectorall-which-one-should-i-use/, accessed 2026-11-14.
