Mastering DOM Manipulation with Vanilla JavaScript

The Document Object Model, or DOM for short, is a fundamental concept in web development. It‘s a programming interface that allows you to interact with and modify the content, structure and style of a web page dynamically using JavaScript.

Essentially, the DOM represents an HTML document as a tree-like structure where each element, attribute and piece of text becomes a node in the tree. JavaScript provides a rich set of methods and properties to traverse and manipulate the DOM tree. Learning these DOM APIs is a core skill for any front-end developer.

In this post, we‘ll explore the most essential concepts and techniques for DOM manipulation using plain JavaScript. While frameworks like React and Vue provide abstractions over the DOM, having a solid grasp of the underlying APIs is still very valuable. Let‘s dive in!

Accessing Elements

The starting point of DOM manipulation is getting access to the elements you want to work with. There are a number of ways to do this:

Accessing Individual Elements

To retrieve a single element, you can use:

  • document.getElementById(id) – selects an element by its unique id attribute
  • document.querySelector(selector) – selects the first element that matches a given CSS selector

For example:


// Select the element with id ‘header‘
const header = document.getElementById(‘header‘);

// Select the first <p> element inside a <div>
const paragraph = document.querySelector(‘div p‘);

Accessing Multiple Elements

To retrieve collections of elements, you can use:

  • document.getElementsByClassName(className) – selects all elements with the given class name
  • document.getElementsByTagName(tagName) – selects all elements with the given tag name
  • document.querySelectorAll(selector) – selects all elements that match a given CSS selector

For example:


// Select all elements with class ‘highlight‘
const highlights = document.getElementsByClassName(‘highlight‘);

// Select all <li> elements const listItems = document.getElementsByTagName(‘li‘);

// Select all <p> elements inside a <div> const paragraphs = document.querySelectorAll(‘div p‘);

Note that getElementsByClassName and getElementsByTagName return "live" node lists that automatically update if the DOM changes. querySelectorAll returns a "static" node list that doesn‘t reflect subsequent changes.

Traversing the DOM Tree

Once you have a reference to an element, you can move around the DOM tree using these properties:

  • node.firstChild – access the first child node
  • node.lastChild – access the last child node
  • node.parentNode – access the parent node
  • node.nextSibling – access the next sibling node
  • node.previousSibling – access the previous sibling node

const list = document.querySelector(‘ul‘);

// Access first child const firstItem = list.firstChild;

// Access parent const parent = list.parentNode;

// Access next sibling const nextElement = list.nextSibling;

These properties allow you to navigate the DOM horizontally (siblings) and vertically (parents and children). Note that whitespace between elements is considered a text node, so these properties may return nodes of type text instead of actual elements.

Manipulating Element Content

There are several ways to get and set the content of an element.

Text Content

To work with plain text content, you can use:

  • node.textContent – gets or sets the text content of an element and all its descendants
  • node.innerText – similar to textContent but more aware of styling and only returns "human-readable" elements

const paragraph = document.querySelector(‘p‘);

// Read text content console.log(paragraph.textContent);

// Modify text content paragraph.textContent = ‘New text content‘;

HTML Content

To work with HTML content, you use:

  • node.innerHTML – gets or sets the HTML content inside an element

// Replace content of a <div> with a new <p>
div.innerHTML = ‘<p>New paragraph content</p>‘;  

Be careful with innerHTML, as it completely replaces the current content. It‘s also a security risk if you‘re inserting untrusted content that may contain XSS attacks.

A safer way to create and insert elements is:

  • document.createElement(tagName) – creates a new element with the given tag name
  • parentNode.appendChild(child) – appends a new child node to a parent
  • parentNode.insertBefore(newNode, referenceNode) – inserts a new node before a reference node

// Create a new <li> element
const li = document.createElement(‘li‘);
li.textContent = ‘New list item‘; 

// Insert into a <ul> const ul = document.querySelector(‘ul‘); ul.appendChild(li);

To remove elements, you use:

  • parentNode.removeChild(child) – removes a child node from its parent

const li = document.querySelector(‘li‘);
const ul = li.parentNode;
ul.removeChild(li);  

Working with Attributes

To get, set, check and remove element attributes, you can use:

  • element.getAttribute(name) – gets the value of an attribute
  • element.setAttribute(name, value) – sets the value of an attribute
  • element.hasAttribute(name) – checks if an attribute exists
  • element.removeAttribute(name) – removes an attribute

const link = document.querySelector(‘a‘);

// Get href attribute console.log(link.getAttribute(‘href‘));

// Add target attribute link.setAttribute(‘target‘, ‘_blank‘);

// Check if title attribute exists if (link.hasAttribute(‘title‘)) {...}

// Remove title attribute link.removeAttribute(‘title‘);

Two attributes that are commonly accessed and modified are id and class:

  • element.id – gets or sets the id of an element
  • element.className – gets or sets the class attribute of an element
  • element.classList – helpful methods to add, remove and toggle CSS classes

const div = document.querySelector(‘div‘);

// Add an id div.id = ‘content‘;

// Add a class div.className = ‘highlight‘;

// Toggle a class div.classList.toggle(‘visible‘);

Advanced Topics

We‘ve covered the most essential concepts of DOM manipulation, but there‘s a lot more to explore:

  • Event handling – how to listen for and respond to events like clicks, keypresses, form submission etc.
  • Styles – getting and setting inline styles using the style property
  • Forms – accessing form fields and their values, form validation
  • Animation – creating animations and transitions using CSS and JavaScript
  • Performance – best practices to minimize repaints and reflows when manipulating the DOM

Some other topics related to the DOM worth exploring are:

  • The difference between the DOM (Document Object Model) and BOM (Browser Object Model) which includes objects like window, screen, location, history etc.

  • How JavaScript frameworks like React and Vue abstract away low-level DOM operations and provide a declarative way to describe UIs as a function of state.

  • Emerging web standards like Web Components and the Shadow DOM that aim to provide stronger encapsulation and reusability of DOM elements.

Conclusion

We‘ve taken a whirlwind tour of the most essential DOM manipulation concepts and techniques using vanilla JavaScript. I hope this post has given you a solid foundation to start working with the DOM in your projects.

Remember that while frameworks abstract a lot of DOM manipulation complexity, having an understanding of the underlying web platform is still incredibly valuable. Don‘t be afraid to peek under the hood of your favorite framework and see how it works its magic!

Happy coding!

Similar Posts