The Document Object Model
The DOM is a programming interface for HTML documents. It represents the page structure as a tree of objects that JavaScript can manipulate.
🔍 Selecting Elements
getElementById
// Select by ID (returns single element or null)
let header = document.getElementById('header');
console.log(header);
// Common usage
let button = document.getElementById('submitBtn');
if (button) {
button.textContent = 'Click Me';
}
getElementsByClassName
// Select by class name (returns HTMLCollection)
let cards = document.getElementsByClassName('card');
console.log(cards.length);
// Convert to array for array methods
let cardsArray = Array.from(cards);
cardsArray.forEach(card => {
console.log(card.textContent);
});
// Live collection (updates automatically)
console.log(cards.length); // e.g., 3
let newCard = document.createElement('div');
newCard.className = 'card';
document.body.appendChild(newCard);
console.log(cards.length); // 4 (updated automatically)
getElementsByTagName
// Select by tag name (returns HTMLCollection)
let paragraphs = document.getElementsByTagName('p');
let divs = document.getElementsByTagName('div');
// Get all elements
let allElements = document.getElementsByTagName('*');
querySelector and querySelectorAll
// querySelector - returns first match (CSS selectors)
let header = document.querySelector('#header');
let firstCard = document.querySelector('.card');
let firstButton = document.querySelector('button');
let complexSelect = document.querySelector('div.card > h2');
// querySelectorAll - returns NodeList of all matches
let allCards = document.querySelectorAll('.card');
let allButtons = document.querySelectorAll('button');
let activeItems = document.querySelectorAll('.item.active');
// NodeList can use forEach directly
allCards.forEach(card => {
console.log(card.textContent);
});
// Advanced selectors
let secondCard = document.querySelector('.card:nth-child(2)');
let notFirst = document.querySelectorAll('.item:not(:first-child)');
let inputs = document.querySelectorAll('input[type="text"]');
let checkedBoxes = document.querySelectorAll('input:checked');
// Selecting within an element
let container = document.querySelector('.container');
let containerButtons = container.querySelectorAll('button');
Modern Shortcuts
// closest - find nearest ancestor matching selector
let button = document.querySelector('.btn');
let card = button.closest('.card');
// matches - check if element matches selector
if (button.matches('.btn-primary')) {
console.log('Primary button');
}
// contains - check if element is descendant
let container = document.querySelector('.container');
let button = document.querySelector('.btn');
console.log(container.contains(button)); // true/false
✏️ Modifying Content
textContent and innerHTML
let div = document.querySelector('.content');
// textContent - plain text only
console.log(div.textContent);
div.textContent = 'New text'; // Replaces all content
// innerHTML - HTML string
console.log(div.innerHTML);
div.innerHTML = 'Title
Paragraph
';
// innerText - similar to textContent but respects CSS
console.log(div.innerText); // Excludes hidden elements
// Security warning: innerHTML is vulnerable to XSS
// Avoid: div.innerHTML = userInput;
// Use: div.textContent = userInput;
Attributes
let img = document.querySelector('img');
// getAttribute and setAttribute
let src = img.getAttribute('src');
img.setAttribute('alt', 'Description');
img.setAttribute('data-id', '123');
// Direct property access (for common attributes)
console.log(img.src);
console.log(img.alt);
img.src = 'new-image.jpg';
// hasAttribute and removeAttribute
if (img.hasAttribute('alt')) {
img.removeAttribute('alt');
}
// Data attributes
let element = document.querySelector('.item');
element.setAttribute('data-user-id', '42');
element.setAttribute('data-role', 'admin');
// Access via dataset
console.log(element.dataset.userId); // '42'
console.log(element.dataset.role); // 'admin'
element.dataset.status = 'active'; // Sets data-status="active"
Classes
let div = document.querySelector('.box');
// className - string of all classes
console.log(div.className); // 'box active large'
div.className = 'box'; // Replaces all classes
// classList - better API (ES5)
div.classList.add('active'); // Add class
div.classList.remove('inactive'); // Remove class
div.classList.toggle('visible'); // Toggle class
div.classList.contains('active'); // Check if has class
// Multiple classes
div.classList.add('large', 'blue');
div.classList.remove('small', 'red');
// Replace class
div.classList.replace('old-class', 'new-class');
// Conditional toggle
div.classList.toggle('active', isActive); // Add if isActive true
Styles
let div = document.querySelector('.box');
// Inline styles (camelCase properties)
div.style.color = 'blue';
div.style.backgroundColor = 'yellow';
div.style.fontSize = '20px';
div.style.marginTop = '10px';
// Read computed style (includes CSS from stylesheets)
let computedStyle = window.getComputedStyle(div);
console.log(computedStyle.color);
console.log(computedStyle.fontSize);
// Set multiple styles
Object.assign(div.style, {
width: '200px',
height: '100px',
border: '1px solid black'
});
// Remove inline style
div.style.color = ''; // Remove color
div.removeAttribute('style'); // Remove all inline styles
// CSS custom properties
div.style.setProperty('--main-color', 'blue');
let value = div.style.getPropertyValue('--main-color');
🏗️ Creating and Removing Elements
Creating Elements
// createElement
let div = document.createElement('div');
div.textContent = 'Hello World';
div.className = 'box';
div.id = 'myBox';
// createTextNode
let text = document.createTextNode('Some text');
// Clone existing element
let original = document.querySelector('.card');
let clone = original.cloneNode(true); // true = deep clone (with children)
// Template strings (create HTML structure)
let html = `
Title
Content
`;
// Create from string (be careful with user input!)
let temp = document.createElement('div');
temp.innerHTML = html;
let card = temp.firstElementChild;
Inserting Elements
let container = document.querySelector('.container');
let newDiv = document.createElement('div');
// appendChild - add as last child
container.appendChild(newDiv);
// insertBefore - insert before reference element
let reference = document.querySelector('.existing');
container.insertBefore(newDiv, reference);
// Modern methods (ES2016)
// before - insert before element as sibling
reference.before(newDiv);
// after - insert after element as sibling
reference.after(newDiv);
// prepend - insert as first child
container.prepend(newDiv);
// append - insert as last child (can append multiple)
container.append(newDiv, 'text', anotherElement);
// insertAdjacentElement
reference.insertAdjacentElement('beforebegin', newDiv); // Before element
reference.insertAdjacentElement('afterbegin', newDiv); // First child
reference.insertAdjacentElement('beforeend', newDiv); // Last child
reference.insertAdjacentElement('afterend', newDiv); // After element
// insertAdjacentHTML - insert HTML string
reference.insertAdjacentHTML('beforeend', 'New paragraph
');
Removing Elements
let element = document.querySelector('.item');
// Modern: remove() method
element.remove();
// Old way: removeChild
let parent = element.parentElement;
parent.removeChild(element);
// Remove all children
let container = document.querySelector('.container');
container.innerHTML = ''; // Fast but loses event listeners
// Or loop through children
while (container.firstChild) {
container.removeChild(container.firstChild);
}
// replaceChild - replace element
let newElement = document.createElement('div');
parent.replaceChild(newElement, element);
// Modern: replaceWith
element.replaceWith(newElement);
🗂️ Traversing the DOM
let element = document.querySelector('.item');
// Parent
console.log(element.parentElement); // Parent element
console.log(element.parentNode); // Parent node (can be non-element)
// Children
console.log(element.children); // HTMLCollection of child elements
console.log(element.childNodes); // NodeList (includes text nodes)
console.log(element.firstElementChild); // First child element
console.log(element.lastElementChild); // Last child element
console.log(element.childElementCount); // Number of children
// Siblings
console.log(element.previousElementSibling); // Previous sibling
console.log(element.nextElementSibling); // Next sibling
// Closest ancestor matching selector
let card = element.closest('.card');
// All matches within element
let buttons = element.querySelectorAll('button');
📊 Element Properties
let element = document.querySelector('.box');
// Dimensions (includes padding, excludes border/margin)
console.log(element.clientWidth);
console.log(element.clientHeight);
// Dimensions (includes padding and border)
console.log(element.offsetWidth);
console.log(element.offsetHeight);
// Scroll dimensions
console.log(element.scrollWidth); // Total width (including overflow)
console.log(element.scrollHeight); // Total height (including overflow)
console.log(element.scrollTop); // Pixels scrolled from top
console.log(element.scrollLeft); // Pixels scrolled from left
// Position relative to offsetParent
console.log(element.offsetTop);
console.log(element.offsetLeft);
console.log(element.offsetParent);
// Bounding rectangle (relative to viewport)
let rect = element.getBoundingClientRect();
console.log(rect.top);
console.log(rect.right);
console.log(rect.bottom);
console.log(rect.left);
console.log(rect.width);
console.log(rect.height);
// Scroll element into view
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
💡 Practical Examples
Create Card Component
function createCard(title, content, imageUrl) {
let card = document.createElement('div');
card.className = 'card';
card.innerHTML = `
${title}
${content}
`;
return card;
}
// Usage
let container = document.querySelector('.cards-container');
let card = createCard('Title', 'Content text', 'image.jpg');
container.appendChild(card);
Toggle Visibility
function toggleElement(selector) {
let element = document.querySelector(selector);
if (element) {
element.classList.toggle('hidden');
// Or: element.style.display = element.style.display === 'none' ? 'block' : 'none';
}
}
// Usage
toggleElement('.modal');
toggleElement('#sidebar');
Form Validation
function validateForm(formSelector) {
let form = document.querySelector(formSelector);
let inputs = form.querySelectorAll('input[required]');
let errors = [];
inputs.forEach(input => {
let errorDiv = input.nextElementSibling;
if (!input.value.trim()) {
input.classList.add('error');
if (errorDiv && errorDiv.classList.contains('error-message')) {
errorDiv.textContent = `${input.name} is required`;
}
errors.push(input.name);
} else {
input.classList.remove('error');
if (errorDiv && errorDiv.classList.contains('error-message')) {
errorDiv.textContent = '';
}
}
});
return errors.length === 0;
}
// Usage
if (validateForm('#contactForm')) {
console.log('Form is valid');
}
Dynamic List
function renderList(items, containerSelector) {
let container = document.querySelector(containerSelector);
container.innerHTML = ''; // Clear existing
let ul = document.createElement('ul');
items.forEach(item => {
let li = document.createElement('li');
li.textContent = item;
li.classList.add('list-item');
ul.appendChild(li);
});
container.appendChild(ul);
}
// Usage
let fruits = ['Apple', 'Banana', 'Orange'];
renderList(fruits, '#fruit-list');
Accordion Component
function createAccordion(items) {
let accordion = document.createElement('div');
accordion.className = 'accordion';
items.forEach((item, index) => {
let section = document.createElement('div');
section.className = 'accordion-item';
let header = document.createElement('div');
header.className = 'accordion-header';
header.textContent = item.title;
header.dataset.index = index;
let content = document.createElement('div');
content.className = 'accordion-content';
content.textContent = item.content;
content.style.display = 'none';
header.addEventListener('click', () => {
let isOpen = content.style.display === 'block';
// Close all
accordion.querySelectorAll('.accordion-content').forEach(c => {
c.style.display = 'none';
});
// Toggle clicked
if (!isOpen) {
content.style.display = 'block';
}
});
section.appendChild(header);
section.appendChild(content);
accordion.appendChild(section);
});
return accordion;
}
// Usage
let items = [
{ title: 'Section 1', content: 'Content 1' },
{ title: 'Section 2', content: 'Content 2' }
];
document.body.appendChild(createAccordion(items));
Lazy Loading Images
function lazyLoadImages() {
let images = document.querySelectorAll('img[data-src]');
let observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
let img = entry.target;
img.src = img.dataset.src;
img.removeAttribute('data-src');
observer.unobserve(img);
}
});
});
images.forEach(img => observer.observe(img));
}
// Usage
// HTML:
lazyLoadImages();
🎯 Key Takeaways
- querySelector: Modern way to select elements using CSS selectors
- textContent: Safer than innerHTML for plain text, prevents XSS
- classList: Better than className for managing classes
- createElement: Create new elements, set properties, then append
- appendChild: Add element as last child, modern: append/prepend
- remove(): Modern way to remove elements from DOM
- dataset: Access data-* attributes easily
- getBoundingClientRect: Get element position and dimensions
lazyLoadImages();