The querySelectorAll() Method – Basics and Syntax
The querySelectorAll() method is a built-in JavaScript function (on the Document and Element objects) that accepts a CSS selector string and returns a **static NodeList** of all matching elements in the document (or within a given element) [1]. In other words, it finds all elements that match the selector(s) and gives you a snapshot list.
Syntax
document.querySelectorAll(selectors)
-
selectors: A string of one or more valid CSS selectors (e.g.,"div.note, #main > p.highlighted") [2]. -
Return value: A non-live (static)
NodeListcontaining each matchingElement(or an emptyNodeListif no matches) [3].
If the selector string is invalid,
querySelectorAll()will throw aSyntaxErrorexception [4].
For example, to select all paragraph (<p>) elements, you can write:
const paragraphs = document.querySelectorAll("p");
This returns a NodeList of every <p> in the document [5]. The order of elements in the list is document order (parents before children, earlier siblings before later siblings) [3]. Because the list is static, it will not automatically update if the DOM changes later; to get fresh results you would call querySelectorAll() again.
Usage and Examples
querySelectorAll() is extremely flexible because it accepts any valid CSS selector. Some common use cases and examples include:
Selecting by Tag Name
const items = document.querySelectorAll("li"); // Finds all <li> elements [5].
Selecting by Class or ID (using CSS syntax)
const mainSection = document.querySelectorAll("#main"); // Select element(s) with id="main"
const buttons = document.querySelectorAll(".btn.primary"); // Select all elements with classes "btn" and "primary"
Note: You can combine selectors with commas to match multiple criteria. For example:
const notesAndAlerts = document.querySelectorAll("div.note, div.alert");
// Returns all <div> elements that have class note or class alert [6].
Selecting Nested or Child Elements
You can use descendant or child selectors for fine-grained selection:
const highlightedParas = document.querySelectorAll("#test div.highlighted > p");
In this example, the code finds <p> elements whose immediate parent is a <div class="highlighted"> inside the container with id="test" [7]. This shows how you can scope selectors to a specific element.
Attribute Selectors and More Complex Queries
const iframes = document.querySelectorAll("iframe[data-src]");
// Selects all <iframe> elements that have a data-src attribute [8].
const activeItems = document.querySelectorAll("#user-list li[data-active='1']");
// Finds all <li> elements inside #user-list that have data-active="1" [9].
Looping Over the NodeList
Once you have the NodeList, you can loop over it just like an array. Modern NodeLists support forEach:
const items = document.querySelectorAll(".item");
items.forEach(item => {
// Do something with each item
item.style.color = "blue";
});
MDN demonstrates this usage: highlightedItems.forEach(userItem => { deleteUser(userItem); }); [10]. (If older browsers are a concern, you can convert the NodeList to an array with Array.from() or spread syntax before using array methods.)
Browser Compatibility
querySelectorAll() is widely supported across all modern browsers and has been part of web standards since DOM Level 3 (around 2004) [11]. Today it works in essentially every major browser and platform.
| Browser | Support |
|---|---|
| Chrome | Supported from version 4 (and all current versions) [12]. |
| Firefox | Supported from 3.5 (with partial or no support in FF2-3) [13]. |
| Safari | Supported from Safari 3.1 onward [14]. |
| Edge | Supported from the very first Edge 12 version onward [15]. |
| Opera | Supported from Opera 10 onward [16]. |
| Internet Explorer | IE9 and newer: Fully supported (in standards mode) [17]. IE8: Partial support (standards mode, limited to CSS 2.1 selectors) [17]. IE7 and below do not support it. |
| Mobile Browsers | All modern mobile browsers (iOS Safari, Chrome for Android, etc.) support querySelectorAll [18] [19]. |
Because support is nearly universal, you can safely use querySelectorAll in most code without polyfills.
Performance Comparison
Performance can vary depending on browser and context. The trade-offs are often between the speed of specialized, simpler methods (which return live collections) and the flexibility of querySelectorAll (which returns a static collection).
Speed of Simple vs. Complex Queries
- Simple Queries (by ID or single class): Generally fastest using the specialized methods like
getElementById,getElementsByClassName, orgetElementsByTagName[20] [21]. For example,getElementById("foo")can be slightly faster thandocument.querySelector("#foo")[21]. - Complex CSS Selectors:
querySelectorAllexcels here because it can handle any valid CSS query (nested, grouped, attribute-based, etc.), but this generality comes with some overhead [20]. - Large Collections: For creating a large collection by class or tag name, the specialized methods are often orders of magnitude faster. Example: Selecting 5,000 elements in a loop showed
getElementsByTagName("p")to be significantly faster thanquerySelectorAll("p")[22].
Accessing Elements in the Result
Interestingly, once the collection is obtained, accessing individual items by index can be faster with the static NodeList (from querySelectorAll) than with a live HTMLCollection (from older methods) [23]. This is because the static list is a snapshot, whereas a live collection may have to re-validate its contents when accessed.
Summary of Best Tool for the Job
| Method | Strength |
|---|---|
getElementById |
Fastest for finding a single element by ID [20] [21]. |
getElementsByClassName / getElementsByTagName |
Faster at creating large collections of elements by class or tag name [20] [22]. Returns a live collection. |
querySelector / querySelectorAll |
Most versatile (supports any CSS selector). Can be slower on large repeated searches, but results can be accessed quickly [25] [23]. Returns a static collection. |
Real-world impact: In practice, performance differences are usually negligible unless you are doing massive or repeated DOM queries. The consensus is to use the method that makes your code clearest.
Caveats and Best Practices
Static vs. Live List
The returned NodeList is static. It will not update if the DOM changes after the query is run (e.g., if elements are added or removed) [26]. If you need a fresh list, you must call querySelectorAll() again. In contrast, getElementsByClassName returns a live HTMLCollection that automatically updates.
CSS Selector Syntax
The string must be a valid CSS selector. Special characters in IDs or classes may need escaping. A malformed selector will throw a SyntaxError [4]. Also, pseudo-elements (like ::before) are not real DOM elements and will return an empty list [27].
Not a Real Array
A NodeList is array-like (it has length, supports indexing, and modern ones have forEach [10]). However, it's not a true Array. If you need array methods like map or filter (especially on older browsers), you must convert it: const arr = Array.from(nodeList);.
Scope to a Container
You can call querySelectorAll on any Element, not just document. This scopes the search to that element's subtree.
const sidebar = document.getElementById("sidebar");
const links = sidebar.querySelectorAll("a.active"); // Finds only <a class="active"> inside #sidebar [7].
Cache Results
If you plan to reuse the query results, **store the result in a variable**. Do not call querySelectorAll() repeatedly inside a loop [24].
const items = document.querySelectorAll(".item"); // Run query once
items.forEach(item => {
// expensive DOM work on item
});
In summary, querySelectorAll() is a powerful and convenient DOM selection method with broad browser support [17]. It excels when using complex CSS-style queries and handling multiple results. Just be mindful of its static result list and choose the right tool for your specific task.
Citations
Sources: Authoritative documentation and benchmarks from MDN and community sources [1] [28] [29] [17] [20] [30] [31].
- [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [27] [28] [29] Document: querySelectorAll() method - Web APIs | MDN. https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
- [11] HTML DOM Document querySelectorAll() Method. https://www.w3schools.com/jsref/met_document_queryselectorall.asp
- [12] [13] [14] [15] [16] [17] [18] [19] querySelector/querySelectorAll | Can I use... Support tables for HTML5, CSS3, etc. https://caniuse.com/queryselector
- [20] [24] javascript - Performance of getElementById vs. getElementsByClassName vs. querySelector - Stack Overflow. https://stackoverflow.com/questions/57159219/performance-of-getelementbyid-vs-getelementsbyclassname-vs-queryselector
- [21] [22] [23] [25] [26] [30] [31] Performance tradeoffs of querySelector and querySelectorAll - DEV Community. https://dev.to/wlytle/performance-tradeoffs-of-queryselector-and-queryselectorall-1074