querySelector or querySelectorAll: which one should I use?
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.
Cite
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.- Teodora VanceStaffModerator: HTML, CSS and front end JavaScript ·
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):
<ul id="menu"> <li class="item">Home</li> <li class="item">Docs</li> <li class="item">Contact</li> </ul>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"); }); });querySelectorgives you one element, so you can use it directly.querySelectorAllgives 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 withdeferas described in why getElementById returns null.Why they behave this way
MDN's querySelector page says the method returns the first element that matches the selector, or
nullif there are no matches. MDN's querySelectorAll page says it returns a static (not live)NodeListof the matching elements, or an empty list if nothing matches, in document order.A
NodeListis a list-like object holding elements. "Static" means it is a snapshot taken at the moment you call it. If you add anotherlilater, 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.alertfinds every div with either class.You can also search inside one element instead of the whole page. This only looks inside
menu:const links = menu.querySelectorAll("a");Which one to pick
You want Use If nothing matches One element that has an id getElementById("menu")orquerySelector("#menu")nullThe first element matching a selector querySelector(".item")nullEvery element matching a selector querySelectorAll(".item")An empty list Our tutorial on querySelector and querySelectorAll shows more selector patterns.
A safe pattern for one element
Because
querySelectorcan returnnull, check before you use the result. This also keeps the rest of your script running when a page does not contain that element:const banner = document.querySelector(".banner"); if (banner) { banner.textContent = "Welcome back"; }With
querySelectorAllyou do not need that check. An empty list loops zero times, so theforEachdoes nothing. That is one reason many people reach for it when an element is optional.Mistakes beginners make
- Using the list like an element.
document.querySelectorAll(".item").addEventListener(...)fails with an error sayingaddEventListeneris not a function, because a list is not an element. Loop withforEach, or write[0]if you only want the first. - Forgetting the dot or the hash.
querySelector("item")looks for a tag nameditem, not a class. Write".item"for a class and"#menu"for an id. - Not handling null. If
querySelectorfinds nothing and you writeel.textContent, you get a TypeError. Check withif (el)first. - Writing an invalid selector. MDN says a selector that is not valid CSS throws a
SyntaxError. An id likethis?elementhas to be escaped withCSS.escape()before you use it in a selector. - Expecting the list to update. The list from
querySelectorAllis a snapshot. Query again after the page changes.
Check this in order
- In the console, run
console.log(document.querySelectorAll(".item")). Do you see a list with the right number of elements? - Copy the same selector into the Elements panel search box (Ctrl+F or Cmd+F). It finds the same matches.
- Check the prefix. Dot for class, hash for id, nothing for a tag.
- Check that the script runs after the elements exist.
- Check which variable holds a list and which holds one element. Name them to match, like
itemanditems.
- Using the list like an element.
Write something first.
Give people something to work with: at least 30 words on what happened and what you tried.
That is too long. Keep it under 6,000 characters.
Write the question as the title, 15 to 140 characters, no links.
Pick a category.
Add a name (2 to 40 characters, no links).
That email address does not look right.
That was quick. Read the thread, then try again.
The form expired. Reload the page and post again.
Something went wrong with the form. Reload and try again.
Please complete the check and post again.
Limit reached for now. Try again later.
This thread is closed to new replies.
This thread no longer accepts replies.
Something went wrong with the form. Reload and try again.
Post a reply or question first (name and email), then this browser can vote, edit and accept answers.
You cannot vote on your own post.
Only the author (within 30 days) or the forum team can do that.
That email already has an account. Use your sign-in link instead.
New accounts are paused for the moment. Try again later.
That was already posted.