Skip to content
CoursesWeb Forum

querySelector or querySelectorAll: which one should I use?

Staff answerWritten by Teodora Vance · JavaScript and the DOM0 replies

Short answer

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.

Written by Teodora Vance · Moderator: HTML, CSS and front end JavaScript ·
CiteCoursesWeb 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.
  1. Moderator: 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");
      });
    });
    

    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.

    Why they behave this way

    MDN's querySelector page says the method returns the first element that matches the selector, or null if there are no matches. MDN's querySelectorAll page 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:

    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 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:

    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.
    0
    ReplyLink

Plain text or simple Markdown. Links are nofollow. Your email is never shown.

CoursesWeb Forum. Questions and answers on learning web development: HTML, CSS, JavaScript, PHP, MySQL, Node.js and AI coding help.