querySelector vs getElementById
By FrontendPro Editorial Team Updated 9/26/2026
Answer
Both find elements in the DOM; they differ in what you can ask for and what you get back.
getElementById takes an id and nothing else. querySelector takes any CSS selector and returns the first match in document order — or null if there is none.
document.getElementById("main"); // id only, no "#"
document.querySelector("#main"); // same element, "#" required
document.querySelector(".card .title"); // anything CSS can express
document.querySelectorAll("li[data-done]");
getElementById | querySelector | |
|---|---|---|
| Accepts | An id string | Any CSS selector |
| Returns | Element or null | First match or null |
| Available on | document only | document and any element |
| Speed | Slightly faster | Fast enough in practice |
The scoping difference matters more than speed
querySelector exists on every element, so you can search within a subtree:
const row = document.querySelector("#row-7");
row.querySelector(".price"); // only inside that row
getElementById only exists on document, so it always searches the whole page.
Live vs static collections
querySelectorAll returns a static NodeList — a snapshot. Elements added later do not appear in it. getElementsByClassName and getElementsByTagName return live collections that update themselves, which surprises people who mutate the DOM while looping over one.
Which to use
getElementById is marginally faster and states the intent plainly when you have an id. querySelector is more flexible and gives you one API for every case. The performance gap is irrelevant outside tight loops over thousands of nodes, so pick for readability. Both return null when nothing matches — always guard before using the result, since null.textContent is a common crash.
