Searching Elements ยท Astro Tech Blog

Searching the DOM

Before you can manipulate an element, you need to find it. JavaScript provides several methods to search the DOM.

Modern Methods: querySelector / querySelectorAll

These are the most versatile โ€” they accept any CSS selector:

document.querySelector('.card')           // first .card element
document.querySelector('#main h2')        // first h2 inside #main
document.querySelectorAll('li')           // all li elements (NodeList)
document.querySelectorAll('[data-type]')  // all elements with data-type
Demo: querySelector in action
HTML
<div id='catalog'>
<div class='card' data-type='fruit'>Apple</div>
<div class='card' data-type='fruit'>Banana</div>
<div class='card' data-type='veg'>Carrot</div>
<div class='card' data-type='veg'>Daikon</div>
</div>
<pre id='sel-output' style='background:#f1f5f9;padding:8px;border-radius:4px;'></pre>
JavaScript
const allCards = document.querySelectorAll('.card');
const fruits = document.querySelectorAll('[data-type=fruit]');
const veg = document.querySelectorAll('[data-type=veg]');
const firstCard = document.querySelector('.card');

const out = document.getElementById('sel-output');
out.textContent =
'All cards: ' + allCards.length + '\\n' +
'Fruits: ' + fruits.length + ' (' + fruits[0].textContent + ', ' + fruits[1].textContent + ')' + '\\n' +
'Vegetables: ' + veg.length + '\\n' +
'First card: ' + firstCard.textContent;
Live Output Window

Legacy Methods: getElement*

These are faster but less flexible. Use them when you know the exact ID, tag, or class:

document.getElementById('header')     // by ID (fastest)
document.getElementsByTagName('p')     // by tag name (live HTMLCollection)
document.getElementsByClassName('card') // by class (live HTMLCollection)
document.getElementsByName('email')   // by name attribute (NodeList)

Live vs Static Collections

This is important!

MethodReturnsLive?
getElementByIdSingle elementN/A
getElementsByTagNameHTMLCollectionYes
getElementsByClassNameHTMLCollectionYes
querySelectorAllNodeListNo
querySelectorSingle elementN/A

Live means the collection updates automatically when the DOM changes.

Demo: Live vs Static Collections
HTML
<ul id='live-demo'>
<li>Item 1</li>
<li>Item 2</li>
</ul>
<button id='add-btn'>Add Item</button>
<pre id='live-output' style='background:#f1f5f9;padding:8px;border-radius:4px;'></pre>
JavaScript
const liveItems = document.getElementsByTagName('li');
const staticItems = document.querySelectorAll('li');

function updateCounts() {
const out = document.getElementById('live-output');
out.textContent =
'Live collection (getElementsByTagName): ' + liveItems.length + '\\n' +
'Static collection (querySelectorAll): ' + staticItems.length;
}

document.getElementById('add-btn').addEventListener('click', function() {
const ul = document.getElementById('live-demo');
const li = document.createElement('li');
li.textContent = 'Item ' + (ul.children.length + 1);
ul.appendChild(li);
// Static items didn't update โ€” show it
const out = document.getElementById('live-output');
out.textContent =
'Live collection: ' + liveItems.length + ' (auto-updated!)' + '\\n' +
'Static collection: ' + staticItems.length + ' (stale โ€” still ' + staticItems.length + ')';
});

updateCounts();
Live Output Window

Closest: Finding Ancestors

closest() walks up the DOM tree to find the nearest matching ancestor:

Demo: closest() demo
HTML
<div class='container'>
<article class='post'>
<h3 class='post-title'>Hello World</h3>
</article>
</div>
<pre id='close-output' style='background:#f1f5f9;padding:8px;border-radius:4px;'></pre>
JavaScript
const title = document.querySelector('.post-title');
const out = document.getElementById('close-output');

const post = title.closest('.post');
const container = title.closest('.container');

out.textContent =
'title.closest(.post): ' + post.tagName + '.post' + '\\n' +
'title.closest(.container): ' + container.className + '\\n' +
'title.closest(.nonexistent): ' + title.closest('.nonexistent');
Live Output Window

Matches: Checking an Element

matches() checks if an element matches a CSS selector:

element.matches('.card')     // true if element has class "card"
element.matches('li:first-child') // true if it's the first li

Method Comparison

MethodReturnsWhen to Use
querySelectorSingle elementAny CSS selector
querySelectorAllNodeList (static)Multiple elements, complex selectors
getElementByIdSingle elementYou know the exact ID
getElementsByTagNameHTMLCollection (live)All elements of a tag
getElementsByClassNameHTMLCollection (live)All elements with a class
closestSingle elementFind ancestor
matchesbooleanCheck if element matches

Key Takeaways

  • querySelector and querySelectorAll are the most flexible โ€” use them by default
  • getElementById is the fastest for single elements with IDs
  • Be aware of live vs static collections to avoid bugs
  • Use closest() to find parent elements matching a selector
  • Use matches() to test an element against a selector