7 Min

DOM-Manipulation in JavaScript: A Beginners Guide

The Document Object Model (DOM) is a structured representation of a web page that allows web developers to interact with HTML and XML documents on the website. It acts as a bridge between the static website and dynamic manipulation through JavaScript, allowing content and style elements to be changed in real time. In front-end development, developers can use the DOM to access, modify or delete individual elements through JavaScript or CSS, enabling interactive user experiences. The DOM is a crucial component in the creation of modern web applications.

The three basic operations on the DOM are:

  1. change elements
  2. add elements
  3. delete elements In this article, we will look at the three operations in turn.

1. Change Elements

Let’s assume we want to change the title of the website “Webdev-Guide.net”. The title Webdev Guide is in the masthead of the website at the top, next to the lightning bolt icon. To access the title, we search for the exact element in the Dev-Console. In the HTML markup of the website, we can see that the title is an anchor link, visible in the HTML element <a class=“site-title” href=“/”>“Webdev Guide”</a>. To access the element, we need to fetch it. We can do this in different ways. Here is one possibility:

let elem = document.getElementsByClassName('site-title')[0];
  • document.getElementsByClassName('site-title'): This method accesses all HTML elements in the document that contain the CSS class site-title. It returns a collection of elements (HTMLCollection).

  • [0]: Since the method returns an HTMLCollection, the first element of this collection is accessed with `[0

  • let elem: This element (the first one with class site-title) is assigned to the variable elem.

Now let’s give the title some other name:

elem.innerHTML = "Godzilla was here"

If you run the code in your dev console, the title “Webdev Guide” should update to “Godzilla was here”.

Here’s another way to change the title:

document.querySelector(".masthead .site-title").innerText = "Rage against the Machine Learning"

The method document.querySelector(".masthead .site-title") looks for the first HTML element in the document that matches the CSS selector. In this case, it looks for the first element within a container with class .masthead that contains class .site-title. The CSS selector ".masthead .site-title" means that site-title is a descendant of masthead.

Here’s another way to change the title:

document.querySelectorAll("a[href='/']")[1].innerHTML = "All fine now?"
  • document.querySelectorAll("a[href='/']"): This method selects all <a> elements (i.e. links) that have an href attribute with the value '/'.

  • [1]: Since we have two anchor links in the DOM (the first anchor is the lightning icon), we select the second element from this list after querySelectorAll. Arrays are zero-based, so the index 1 is the second element. This is our .site-title

  • .innerHTML = "All fine now?": This instruction sets the HTML content of the selected link (the second a tag with href='/') to the text "All fine now?".

As you can see, there are several ways to manipulate the DOM.

Now let’s look at how we can create and add new HTML elements.

2. Add Elements

If we want to add an element, we first have to create the element and then add it to the DOM with an instruction where we want to place the element:

// We create a new element:
let elem = document.createElement("div")
elem.innerHTML = "New Content coming Soon!"

// We select the element to which we want to prepend the new element:
let icon = document.querySelector("a[href='/']")

// We add the new element
icon.parentNode.insertBefore(elem, icon.nextSibling)

The new element should now appear in the masthead of the website.

Why is icon.parentNode.insertBefore(elem, icon.nextSibling) such a cumbersome statement? It’s a constant problem in the DOM as well as in all node-based data structures in general:

Take any element in the document. The element only knows about itself. If you want to do something to the left or right of the document, you have to select the parent element. Child elements do not have access to the parent element, but parent elements do have access to their child elements. So if you want to add elements to the DOM, you have to find the parent element. You do this with icon.parentNode.

The basic syntax for adding elements is:

referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);

Where referenceNode is the node you want to put newNode after. If referenceNode is the last child within its parent element, that’s fine, because referenceNode.nextSibling will be null and insertBefore handles that case by adding to the end of the list.

3. Remove Elements

Removing elements from the DOM is simple:

element.remove()

Let’s say we want to delete the icon from the DOM. We do this with:

let logo = document.querySelector(".site-logo")
logo.remove()

We could also have hidden the logo with:

let logo = document.querySelector(".site-logo")
logo.style.visibility = "hidden"

But that would just leave the logo invisible in the DOM, whereas the logo.remove() command causes the element to be explicitly deleted from the DOM.

If your console reports an error: Cannot read properties of null, it is probably because you have already deleted the logo element and are therefore trying to access null. To fix the error, reload the window by pressing F5 or typing document.location.reload in the console and try again.


A Practical Example

The examples I gave are important for understanding the DOM, but not really practical. Here is a practical example for you:

javascript:(function() {
  var h = document.getElementsByTagName("head")[0];
  var s = document.createElement("style");
  s.setAttribute("type", "text/css");
  s.appendChild(document.createTextNode(`
	  html { 
		  -webkit-filter: invert(100%) hue-rotate(180deg) contrast(70%) !important; 
		  background: #fff;
	  } 
	  
	  .line-content {
		  background-color: #fefefe;
	  }`
	));
  h.appendChild(s);
})();

Do you understand what is happening in this code?

If you are wondering whether you should type the code or whether it is enough to copy-paste the code into your console: Copy-pasting is allowed, but never copy code that you do not understand. As a web developer, you need to know what you are doing, especially when the code becomes dangerous. You can safely copy-paste the above code into your dev console, because the code is safe (or is it? ;))

The code does the following:

  1. Self-calling function: The code is encapsulated in a self-calling anonymous function, which means that it is executed immediately after its definition, without the need for any further instructions to call the function. You can recognize self-calling functions by the fact that a function call is made via () immediately after the closing curly bracket } (in this case })).

  2. Get head element: document.getElementsByTagName("head")[0] is used to select the first <head> element of the document. The <head> section is usually where metadata, scripts and stylesheets of the web page are loaded.

  3. Create new <style> element: The code creates a new <style> element using document.createElement("style"). This is an HTML tag used to embed CSS rules directly into the document.

  4. Define CSS rules: s.appendChild(document.createTextNode(...)) is used to insert the CSS rules into the created <style> element. The rules include:
    • Inversion and color matching: The html rule applies a CSS filter that inverts all the content of the page, shifts the color tones by 180 degrees and reduces the contrast to 70%. This significantly changes the entire appearance of the web page, similar to a “dark mode”.
    • Background color of the .line-content class: A specific rule is added for elements with the class .line-content that sets their background color to a light gray (#fefefe).
  5. Inserting the <style> element: The created <style> element with the new CSS rules is inserted into the <head> element of the web page, immediately applying the defined styles to the page.

Result

  • The entire website is inverted in color (white areas become black, and vice versa), the colors are adjusted, and elements with the class .line-content get a white background color.

This code could be used to apply a kind of “dark mode” or a special visual filter to a website.

For websites that only have the bright theme, such a dark theme switcher may be useful, but with the next page refresh (F5) the theme is reset, and we have to enter and execute the function in the dev console again to enjoy our dark theme. Wouldn’t it be more practical if our dark theme switcher was available for all websites that we visit with our web browser, globally and always available, so to speak? We achieve this using bookmarklets:

Bookmarklets

The bookmarklet is the little brother of the browser plug-in. It is saved as a bookmark and executes Javascript on the page you are currently on. We will make our dark theme available as a bookmarklet. This is how it works:

  1. Add a new bookmark:
    1. Navigate to your web browser’s bookmark manager. In most browsers you can do this using Ctrl+Shift+O, or you can click on “Bookmarks” in the browser menu and then select “Bookmark Manager”
    2. Right-click on the bookmarks bar or the folder you want to insert the bookmarklet into and select “Add new bookmark” or “Add page”.
    3. Configure the bookmark:
    4. Enter a name in the “Name” field.
  2. Paste the Javascript code into the “URL” field. Important: Put javascript: at the beginning, i.e.: javascript:(function() {... to tell the web browser that the bookmark is not a regular bookmark, but Javascript code.
  3. Save the bookmark: Click “Save” or “Done” to add the bookmarklet to your bookmarks bar or folder.

The dark theme is now available for every website you visit. Go to any website and click on the bookmarklet you just added. Some websites look pretty ugly in the dark theme, but you will find that webdev-guide.net looks stylish in the dark theme!

Updated: