All topics
DOMbeginner

DOM Manipulation Basics

Selecting, creating, modifying, and removing elements from the live document tree using core DOM APIs.

The DOM is the live tree of the page. Changing it changes what the user sees, immediately.

The DOM is like a building's live floor plan blueprint that also happens to be the actual building — walking up and modifying a wall (element) via querySelector immediately changes the real physical structure, which is why builders (browsers) try to batch several wall changes together before recalculating the whole building's structural integrity (reflow) instead of doing it after every single nail.

Key Concepts

1
Selecting.
    document.querySelector('.card')       // the first match
    document.querySelectorAll('.card')    // all -- a static NodeList
    document.getElementById('main')       // fastest, by id
2
querySelectorAll returns a static list — a snapshot. getElementsByClassName returns a live collection that updates as the DOM changes, which surprises people iterating while removing.
querySelectorAllgetElementsByClassName
3
Creating and inserting.
    const el = document.createElement('div');
    el.textContent = 'Hello';
    el.className = 'card';
    parent.append(el);
4
    parent.append(a, b, 'text');     // several, and strings
    el.before(x); el.after(y);
    el.remove();                     // no parent needed
5
append and remove replaced appendChild and parentNode.removeChild, and are worth using.
appendremoveappendChildparentNode.removeChild
6
textContent against innerHTML.
    el.textContent = userInput;   // safe -- treated as text
    el.innerHTML = userInput;     // parses HTML -- XSS
textContentinnerHTML
7
That is the security line. Any user-supplied string assigned to innerHTML can execute script. Use textContent unless you are deliberately inserting markup you control.
innerHTMLtextContent
8
Attributes against properties.
    el.setAttribute('data-id', '5');
    el.dataset.id;                // '5' -- the data-* API
    el.value                      // the current value
    el.getAttribute('value')      // the ORIGINAL HTML attribute
9
For form fields those two diverge as soon as the user types, which is a common source of "the value is wrong".
10
Batch your changes. Each insertion into the live tree can trigger layout:
11
    // 1000 reflows
    items.forEach(i => list.append(makeItem(i)));
12
    // one
    const frag = document.createDocumentFragment();
    items.forEach(i => frag.append(makeItem(i)));
    list.append(frag);
13
And avoid layout thrashing — alternating reads and writes forces recalculation each time:
14
    // bad: read, write, read, write
    els.forEach(el => { el.style.height = el.offsetHeight + 10 + 'px'; });
15
    // good: read all, then write all
    const hs = els.map(el => el.offsetHeight);
    els.forEach((el, i) => el.style.height = hs[i] + 10 + 'px');
16
What the interviewer is probing.1. "Why is innerHTML risky?" Probing: the injection risk. Stalls: "It is slower." *Moves up:* it parses and executes markup, so untrusted content becomes XSS; textContent sets text safely.
17
2. "What is the difference between textContent and innerText?" Probing: the layout cost. Stalls: "The same." Moves up: innerText respects styling and visibility so it forces a reflow to compute; textContent reads the raw text and is faster.
18
3. "How do you add many elements efficiently?" Probing: batching. Stalls: "Append in a loop." Moves up: build in a DocumentFragment or an HTML string and insert once, so the browser lays out once rather than per element.
19
4. "querySelector or getElementById?" Probing: the trade. Stalls: "Always querySelector." Moves up: getElementById is faster and clearer for an id; querySelector is worth it for anything more complex.