JavaScript DOM Manipulation

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

TL;DR

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

Selecting Elements and Editing Content

    getElementById()

    Faster than querySelector, but only matches by unique ID.

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

    Finds the first element that matches any valid CSS selector.

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

    Gets every matching element as a static NodeList for looping.

    document.querySelectorAll('.item');
    NodeList methods

    Supports forEach; use Array.from() for full array methods.

    Array.from(els).map(e => e.textContent);
    textContent

    Escapes everything assigned, unlike innerHTML.

    title.textContent = 'New Title';
    innerHTML

    Inserts HTML markup; use only with trusted content.

    title.innerHTML = '<em>New Title</em>';
    insertAdjacentHTML()

    Inserts markup at a position without replacing existing content.

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

    Embed values in markup cleanly.

    el.innerHTML = `<em>${n}</em> online`;

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');

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

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');

Tips

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

Warnings

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

In Practice

FAQ