Real DOM

What is the Real DOM?

The Document Object Model (DOM) is a programming interface for HTML documents. It represents the page as a tree of objects that can be manipulated with JavaScript.

Try DOM Manipulation

Code Editor
Console Output
Click "Run" to execute your code...

Example 1: Selecting DOM Elements

// getElementById - returns single element
const header = document.getElementById('header');
console.log(header);

// getElementsByClassName - returns HTMLCollection (live)
const items = document.getElementsByClassName('item');
console.log(items); // HTMLCollection
console.log(items.length);

// getElementsByTagName - returns HTMLCollection
const paragraphs = document.getElementsByTagName('p');
console.log(paragraphs);

// querySelector - returns first matching element
const firstItem = document.querySelector('.item');
const button = document.querySelector('#submit-btn');
const input = document.querySelector('input[type="text"]');

// querySelectorAll - returns NodeList (static)
const allItems = document.querySelectorAll('.item');
allItems.forEach(item => {
  console.log(item.textContent);
});

// Difference: HTMLCollection vs NodeList
// HTMLCollection: live, auto-updates when DOM changes
// NodeList from querySelectorAll: static snapshot

// Parent-child relationships
const parent = document.getElementById('parent');
const children = parent.children;        // HTMLCollection
const childNodes = parent.childNodes;    // NodeList (includes text nodes)
const firstChild = parent.firstElementChild;
const lastChild = parent.lastElementChild;

// Siblings
const element = document.querySelector('.item');
const next = element.nextElementSibling;
const prev = element.previousElementSibling;

// Parent
const parentEl = element.parentElement;
const closest = element.closest('.container'); // Finds closest ancestor

Example 2: Creating and Modifying Elements

// Creating elements
const div = document.createElement('div');
const text = document.createTextNode('Hello World');
const fragment = document.createDocumentFragment(); // For batch operations

// Setting content
div.textContent = 'Plain text (safe from XSS)';
div.innerHTML = '<span>HTML content (be careful!)</span>';

// Setting attributes
div.id = 'myDiv';
div.className = 'container';
div.setAttribute('data-id', '123');
div.setAttribute('role', 'button');

// Getting attributes
const id = div.id;
const dataId = div.getAttribute('data-id');
const hasRole = div.hasAttribute('role');

// Removing attributes
div.removeAttribute('role');

// Working with classes
div.classList.add('active');
div.classList.remove('inactive');
div.classList.toggle('visible');
div.classList.contains('active'); // true
div.classList.replace('old-class', 'new-class');

// Styles
div.style.color = 'red';
div.style.backgroundColor = 'blue';
div.style.fontSize = '16px';

// Better: use CSS classes instead of inline styles
// div.classList.add('styled');

// Data attributes
div.dataset.userId = '456';
div.dataset.userName = 'John';
console.log(div.dataset.userId); // '456'

// Adding to DOM
const container = document.getElementById('container');
container.appendChild(div);
container.insertBefore(div, container.firstChild);
container.replaceChild(newElement, oldElement);

// Modern methods
container.append(div, 'text', otherElement);   // Can add multiple
container.prepend(div);                         // Add to beginning
container.before(div);                          // Add before element
container.after(div);                           // Add after element
div.replaceWith(newElement);                    // Replace element
div.remove();                                   // Remove from DOM

Example 3: DOM Manipulation Examples

// Example 1: Creating a list dynamically
function createList(items) {
  const ul = document.createElement('ul');
  ul.className = 'item-list';
  
  items.forEach(item => {
    const li = document.createElement('li');
    li.textContent = item;
    li.className = 'list-item';
    ul.appendChild(li);
  });
  
  return ul;
}

const fruits = ['Apple', 'Banana', 'Orange'];
const list = createList(fruits);
// document.body.appendChild(list);

// Example 2: Creating a card component
function createCard(title, description, imageUrl) {
  const card = document.createElement('div');
  card.className = 'card';
  
  card.innerHTML = `
    <img src="${imageUrl}" alt="${title}" class="card-image">
    <div class="card-body">
      <h3 class="card-title">${title}</h3>
      <p class="card-description">${description}</p>
      <button class="btn btn-primary">Learn More</button>
    </div>
  `;
  
  return card;
}

const card = createCard(
  'JavaScript',
  'Learn JavaScript fundamentals',
  '/images/js.png'
);

// Example 3: Table generation
function createTable(data) {
  const table = document.createElement('table');
  table.className = 'data-table';
  
  // Create header
  const thead = document.createElement('thead');
  const headerRow = document.createElement('tr');
  Object.keys(data[0]).forEach(key => {
    const th = document.createElement('th');
    th.textContent = key;
    headerRow.appendChild(th);
  });
  thead.appendChild(headerRow);
  table.appendChild(thead);
  
  // Create body
  const tbody = document.createElement('tbody');
  data.forEach(row => {
    const tr = document.createElement('tr');
    Object.values(row).forEach(value => {
      const td = document.createElement('td');
      td.textContent = value;
      tr.appendChild(td);
    });
    tbody.appendChild(tr);
  });
  table.appendChild(tbody);
  
  return table;
}

const users = [
  { name: 'John', age: 30, city: 'New York' },
  { name: 'Jane', age: 25, city: 'London' }
];
const table = createTable(users);

Example 4: Performance Optimization

// Bad: Multiple reflows (slow)
const container = document.getElementById('container');
for (let i = 0; i < 1000; i++) {
  const div = document.createElement('div');
  div.textContent = `Item ${i}`;
  container.appendChild(div); // Triggers reflow each time!
}

// Good: Use DocumentFragment (fast)
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
  const div = document.createElement('div');
  div.textContent = `Item ${i}`;
  fragment.appendChild(div);
}
container.appendChild(fragment); // Single reflow!

// Better: Build HTML string (fastest for simple cases)
let html = '';
for (let i = 0; i < 1000; i++) {
  html += `<div>Item ${i}</div>`;
}
container.innerHTML = html;

// Batch DOM reads and writes
// Bad: Interleaving reads and writes
const elements = document.querySelectorAll('.item');
elements.forEach(el => {
  const height = el.clientHeight; // Read (forces layout)
  el.style.height = height * 2 + 'px'; // Write
});

// Good: Batch reads, then batch writes
const elements = document.querySelectorAll('.item');
const heights = Array.from(elements).map(el => el.clientHeight);
elements.forEach((el, i) => {
  el.style.height = heights[i] * 2 + 'px';
});

// Use classList instead of className
// Bad: Triggers reflow
element.className = 'class1 class2 class3';

// Good: Batched internally
element.classList.add('class1', 'class2', 'class3');

// Detach element before multiple modifications
const list = document.getElementById('list');
const parent = list.parentNode;
parent.removeChild(list);

// Make modifications
list.classList.add('modified');
list.style.color = 'red';
// ... many more changes

// Reattach
parent.appendChild(list);

Example 5: DOM Properties and Methods

// Element dimensions and position
const element = document.querySelector('.box');

// Size (including padding, excluding border)
console.log(element.clientWidth);
console.log(element.clientHeight);

// Size (including padding and border)
console.log(element.offsetWidth);
console.log(element.offsetHeight);

// Size (including padding, border, and scrollbar)
console.log(element.scrollWidth);
console.log(element.scrollHeight);

// Position relative to offsetParent
console.log(element.offsetLeft);
console.log(element.offsetTop);

// Precise position and size
const rect = element.getBoundingClientRect();
console.log(rect.top, rect.left, rect.width, rect.height);

// Scroll position
console.log(element.scrollTop);
console.log(element.scrollLeft);
element.scrollTop = 100; // Scroll to position

// Scroll to element
element.scrollIntoView({ behavior: 'smooth', block: 'center' });

// Clone element
const clone = element.cloneNode(true); // true = deep clone (with children)
const shallowClone = element.cloneNode(false);

// Check if element contains another
const container = document.getElementById('container');
const child = document.querySelector('.child');
console.log(container.contains(child)); // true

// Check if elements match selector
console.log(element.matches('.box')); // true
console.log(element.matches('#myId')); // false

// Comparing nodes
const el1 = document.getElementById('el1');
const el2 = document.getElementById('el2');
console.log(el1.isEqualNode(el2)); // Same structure and content?
console.log(el1.isSameNode(el2));  // Same object reference?

// Focus management
const input = document.querySelector('input');
input.focus();
input.blur();
console.log(document.activeElement); // Currently focused element

Key Points

  • DOM is a tree structure representing HTML document
  • Use querySelector/querySelectorAll for flexible element selection
  • Minimize DOM manipulations - batch operations when possible
  • Use DocumentFragment for adding multiple elements
  • classList is better than className for class management
  • Avoid layout thrashing (interleaved reads and writes)
  • Real DOM operations are expensive - Virtual DOM helps optimize