JavaScript DOM Manipulation

Select, edit, style, and create DOM elements with vanilla JavaScript and handle user events.

TL;DR

  1. 01Select elements with querySelector() and getElementById() before reading or editing them.
  2. 02Edit content with textContent, and toggle styles with classList.
  3. 03Attach addEventListener() to respond to clicks and other user actions.

Tips

  1. 01Use textContent instead of innerHTML when inserting user-provided text, since it prevents HTML injection and runs faster.
  2. 02Attach one addEventListener() call to a parent element instead of many on children, so new elements work automatically through delegation.

Warnings

  1. 01Adding many elements one by one causes slow page reflows, so use a DocumentFragment for batch inserts in large lists.
  2. 02Setting innerHTML with untrusted or user-supplied content opens the door to script injection, so sanitize it or use textContent instead.

Selecting Elements

    getElementById()

    Faster than querySelector, but only matches elements by their unique ID.

    const title = document.getElementById('title');
    querySelector()

    Finds the first element that matches any valid CSS selector.

    const btn = document.querySelector('.btn');
    querySelectorAll()

    Gets every matching element as a static NodeList for looping.

    const els = document.querySelectorAll('.item');
    NodeList methods

    NodeLists support forEach, but use Array.from() for full array methods.

    Array.from(items).map(el => el.textContent);
    Cache selections

    Cache repeated selections in a variable to keep your code fast.

    const btn = document.querySelector('.btn');

Editing Content

    textContent

    Escapes everything you assign to it, unlike innerHTML, which parses markup.

    title.textContent = 'New Title';
    innerHTML

    Inserts HTML markup, but only with trusted content since it executes scripts.

    title.innerHTML = '<em>New Title</em>';
    Reading text

    Read element text the same way you set it, using the same properties.

    console.log(title.textContent);
    insertAdjacentHTML()

    Inserts markup at a specific position without replacing existing content.

    list.insertAdjacentHTML('beforeend', html);
    Template literals

    Use template literals to build dynamic strings before assigning them.

    title.innerHTML = `<em>${name}</em> logged in`;

Styling Elements

    Inline styles

    Work well for one-off changes, but classList methods scale better overall.

    btn.style.backgroundColor = 'tomato';
    classList.add()

    Adds a CSS class to the element for cleaner styling control.

    btn.classList.add('active');
    classList.toggle()

    Toggles a class on and off with a single method call.

    btn.classList.toggle('highlight');
    classList.remove()

    Removes a class when the state changes back to normal.

    btn.classList.remove('active');
    classList.contains()

    Checks whether an element currently has a given class applied.

    btn.classList.contains('active');

Creating and Removing

    createElement()

    Builds a new element that isn't yet attached to the DOM.

    const newDiv = document.createElement('div');
    newDiv.textContent = 'Hello!';
    appendChild() / append()

    Inserts the new element into the DOM; append() also accepts strings and multiple arguments.

    document.body.appendChild(newDiv);
    remove()

    Removes an element from the DOM by calling remove() on it directly.

    newDiv.remove();
    insertBefore() / prepend()

    Use these to control the exact position where new elements land.

    list.prepend(newItem); // inserts first
    DocumentFragment

    Batches multiple appends into one operation, avoiding repeated page reflows.

    const frag = document.createDocumentFragment();
    items.forEach(i => frag.append(i));
    list.append(frag);

Traversing the DOM

    parentElement

    Accesses the direct parent of the current element, or null.

    const parent = btn.parentElement;
    children

    Accesses all direct children of an element as a live HTMLCollection.

    const items = list.children; // live collection
    Sibling properties

    Move to the next or previous sibling at the same level.

    const next = el.nextElementSibling;
    const prev = el.previousElementSibling;
    closest()

    Finds the nearest matching ancestor starting from any element, or null.

    const card = btn.closest('.card');
    contains()

    Checks whether one element is a descendant of another, anywhere in the tree.

    document.body.contains(btn); // true or false

In Practice

FAQ