The querySelectorAll() method is a powerful and versatile tool in the modern Web API that returns a static NodeList representing a collection of the document’s elements that match the specified group of selectors. Like its sibling querySelector(), it leverages the browser’s CSS selector engine, allowing you to target elements with the same precision and complexity as you would in a stylesheet.
1. Syntax and Core Mechanics
The method can be executed on the global document object or on an individual Element node to restrict the search.
const nodeList = parentNode.querySelectorAll(selectors);
Parameters
- selectors: A string containing one or more valid CSS selectors. You can separate multiple selectors with commas (e.g., “div, .sidebar, #main-btn”).
Return Value
- Returns a static NodeList.
- If no matches are found, it returns an empty NodeList (length of 0), rather than null. This is a crucial distinction from querySelector(), as it prevents “Cannot read property of null” errors when looping.
2. Key Characteristic: The “Static” NodeList
The most significant technical detail of querySelectorAll() is that the returned collection is static.
Unlike “live” collections (like those returned by getElementsByClassName), a static NodeList is a snapshot in time. If you add or remove elements from the DOM after the query is made, the NodeList will not update automatically.
const staticList = document.querySelectorAll('.item');
console.log(staticList.length); // 3
// Add a new element to the DOM
const newItem = document.createElement('div');
newItem.className = 'item';
document.body.appendChild(newItem);
console.log(staticList.length); // Still 3 (The snapshot hasn't changed)
3. Advanced Selection Examples
Because it supports the full CSS specification, you can perform highly specific queries that would be nearly impossible with legacy methods.
A. Attribute and State Selectors
Find all checkboxes that are currently checked.
const checkedBoxes = document.querySelectorAll('input[type="checkbox"]:checked');
B. Combinators and Pseudo-classes
Select all list items that are even-numbered and sit inside an active navigation menu.
const evenNavItems = document.querySelectorAll('nav.active ul > li:nth-child(even)');
C. Multiple Selector Groups
Select all headings and all elements with a specific data attribute.
const vitalElements = document.querySelectorAll('h1, h2, h3, [data-priority="high"]');
4. Iterating Over Results
The NodeList returned by querySelectorAll() is “array-like.” Modern browsers allow you to use the .forEach() method directly on the NodeList, which is the most common way to apply logic to multiple elements.
const cards = document.querySelectorAll('.profile-card');
cards.forEach((card, index) => {
card.style.transitionDelay = `${index * 100}ms`;
card.classList.add('visible');
});
Converting to a Real Array
If you need to use advanced array methods like .map(), .filter(), or .reduce(), you must convert the NodeList using the spread operator or Array.from().
const buttons = document.querySelectorAll('button');
const buttonArray = Array.from(buttons);
const primaryButtons = buttonArray.filter(btn => btn.classList.contains('btn-primary'
5. Practical Use Case: Mass Event Binding
querySelectorAll() is the standard way to attach event listeners to a group of similar components, such as a gallery of images or a group of accordion tabs.
const accordionHeaders = document.querySelectorAll('.accordion-header');
accordionHeaders.forEach(header => {
header.addEventListener('click', () => {
const panel = header.nextElementSibling;
panel.classList.toggle('open');
});
});
