What is the DOM, Actually?

What is the DOM, Actually?

Understanding the Document Object Model in and out
Ferenc Almasi • Last updated 2024 February 21 • Read time 9 min read
There are more than 1.5 billion active websites on the internet all made up of the same model; the Document Object Model or DOM for short. What is it?

At the writing of this tutorial, there are more than 1.5 billion active websites on the internet with new sites popping up every second. They're all made up of the same model; the Document Object Model or DOM for short.

The total number of live websites reported by Internet Live Stats
The total number of live websites reported by Internet Live Stats

One of the core steps that is responsible for rendering a website to your screen. To better understand the DOM, however, we first need to understand how websites are rendered.


How Websites are Rendered

To give you a brief overview, the steps it takes to turn HTML, CSS, and JavaScript into Facebook, X, Medium, or this very page is called the “Critical Rendering Path”, or CRP for short. It's made up of 5 different steps, each one building on top of the previous one.

The steps of the critical rendering path
The steps of the critical rendering path

The very first step of the CRP is about constructing the DOM from the HTML markup we write. So does that mean that HTML and the DOM are not the same? Is there a difference at all?


What is the Difference Between HTML and the DOM

You might be thinking that the DOM is the HTML we write or we see when we inspect the source of a website. This is however not the case. You may also be tempted to say that it then must be the “Elements” panel in DevTools. But this is only partially true.

Elements tab in DevTools
The markup we see in the “Elements” tab in DevTools

While DevTools certainly provides a great way to visualize the DOM, it actually does more than that. It also provides additional information on pseudo-elements that are technically not part of the DOM.

Pseudo-elements are added through CSS. Since they're not part of the DOM, this also means we can’t modify them directly through JavaScript. However, there is a workaround to read values from pseudo-elements. For example, we can use the code below to get the content of a ::before element on the .pseudo element:

Copied to clipboard!
// Get the content of the :before element on .pseudo
window.getComputedStyle(document.querySelector('.pseudo'), ':before')
      .getPropertyValue('content')
window and document are global objects we can access anywhere

Here we used two global objects that can be used anywhere in JavaScript. window references the actual browser window, while document references the DOM. We can access the DOM by referencing the global document object. For example, to get an element with a class name of .pseudo, we can use the querySelector method:

Copied to clipboard! Playground
<span class="pseudo">
    This element has a pseudo class
</span>
<script>
    const pseudoElement = document.querySelector('.pseudo')

    // Logs the properties of the DOM element to the console
    console.log(pseudoElement)
    console.log(pseudoElement.innerText)
</script>
Pass a CSS selector to querySelector to get a DOM element

The element above has a class name of pseudo. There is also an innerText property that returns the text contained within this element.

Notice that since we're inside an HTML file, we need to wrap our JavaScript code between script tags.

So even though the DOM looks exactly like the HTML we write, it's more than that. Imagine we forgot to close one of our tags in our HTML markup, or we completely omit a required tag, such as our <head>. If we take a look at this document in DevTools, we'll notice the tag has been automatically inserted for us. The browser corrected the invalid HTML during DOM creation.

The DOM corrects invalid HTML markup
Looking to improve your skills? Check out our interactive course to master HTML from start to finish.
Master HTMLinfo Remove ads

How the DOM is Created

When the browser constructs the Document Object Model, it goes through five different steps. This is called the critical rendering path that we have talked about before. At the end of the fifth step, we get the DOM. Let’s see the responsibilities of each step:

First, the browser reads the HTML file that it receives from a server or from a local machine. At this stage, the file is nothing more than a string of bytes. This step is called reading.

DOM reading step
When the computer reads the file, it only sees a string of bytes that makes up the HTML file

Next, the bytes are converted into characters based on a specified encoding we provide in our <meta charset="..." /> attribute. This is usually set to UTF-8. At the end of this step, we get back the same version of the file we have just created.

DOM conversion step
When conversion happens, the file turns into a human-readable format

After conversion, the browser can start creating tokens for valid HTML elements — that are specified in the HTML standard — such as our <head> or our <body>. Each of these tokens will have its own set of rules. This step is called tokenization.

DOM tokenization step
Tokenization means that each HTML tag gets their own rules

At the last (lexing) stage, the tokens are converted into objects that define their set of properties.

DOM lexing step
When lexing happens, each HTML tag gets its own properties, turning them into DOM elements

After this step, If we use console.dir, we can log out the properties of a DOM element to the console. Make sure you pass a DOM element to it (for example by using document.querySelector).

Logging out properties of DOM elements
Logging out properties of DOM elements can be done by using console.dir

Lastly, the different objects are linked together into a tree structure that defines the relationship between each of the elements. Now we also know the parent-child relationship of each element. The output of this final step is the Document Object Model:

Creating the DOM
Creating the DOM is about linking different DOM elements together

Putting everything together, these are the steps required for the browser to construct the DOM:

Steps to create the DOM
The steps required in order to create the DOM

What DOM Can Be Used For

So what is the use of the DOM? What can we use it for? As mentioned before, when the browser constructs the DOM, it does a great job of validating invalid elements. However, this is not an encouragement to write invalid HTML. More importantly, the DOM functions as an API that can be used to manipulate HTML.

Manipulating the DOM through JavaScript

When we modify an element inside the HTML, we do not directly make changes to the HTML file. Instead, we're interacting with the DOM that in return changes our elements.

  • index.js index.js
  • index.html index.html
Refresh

In the above example, we change the text and its style and also add some data attributes. To know what kind of properties are available on a DOM element, it's recommended to log them to the console, as we did in the previous example. We can see that style-related attributes are all located under the style object (using camelCase), while data attributes are all located under the dataset object. Try changing the backgroundColor property to #F0F to see how it affects the element.

If you select a DOM element in the “Elements” panel, you can also reference it inside the console with $0. You can also do right-click → “Store as global variable”.  

We can also use JavaScript to dynamically create new HTML elements and attach them to the DOM that has already been created by the browser:

Copied to clipboard! Playground
<div class="html-container">
    <div>DOM element will be inserted below:</div>
</div>
<script>
    const span = document.createElement('span');
    const container = document.querySelector('.html-container');

    span.innerText = 'đź‘‹';

    container.appendChild(span);
</script>
Appending element to existing DOM elements

Copy and paste the div element into index.html in the editor to test the code, then paste the script without the script tags into index.js to add the JavaScript. We can do the opposite and remove elements by calling remove on the DOM element. Try to remove the span by calling span.remove().

Interacting with the DOM through JavaScript

Interaction is everywhere in applications. The DOM can also be used to attach event listeners in JavaScript to respond to certain user actions. For example, if someone clicks on an element or an input changes.

To achieve this, we can use the addEventListener method on a DOM element, with a type of listener and a callback function. In the below example, it'll attach an event listener to the button below. Click on the button to see the alert triggered.

  • index.js index.js
  • index.html index.html
Refresh

Here we used thegetElementById method that gets an element by its ID attribute. The button above has the ID of #click-me. JavaScript has a couple of other event types, such as change or keyup:

Copied to clipboard! Playground
<input type="text" id="text-input" />
Input's value: <span id="input-value"></span> 

<script>
    const textInput = document.getElementById('text-input')
    const inputValue = document.getElementById('input-value')

    textInput.addEventListener('keyup', event => {
        // We can access the value of the input
        // using event.target.value
        inputValue.innerText = event.target.value
    })
</script>
Updating a DOM element on every keystore
  • Lines 5-6: We select the DOM elements using document.getElementById which expects the ID attribute of a DOM element.
  • Lines 8-12: We attach a keyup event listener to the input element using the addEventListener method.
  • Line 11: Inside the callback of the addEventListener, we change the text of the span element by setting its innerText property to event.target.value, which is the value of the input field.

Try to copy and paste the code example in the editor above to test the code, similar to the previous example. If you enter a value into the input, it'll be instantly reflected next to the input.

Lastly, we can not only create individual elements through JavaScript and add interactions, but we can also create an entire DOM inside our document. This is called shadow DOM.


What is the Shadow DOM

The shadow DOM is used for encapsulation. It's an important part of web components. We can use it to keep our structure, our styles, and the behavior associated with it separate from our main document.

Shadow DOM shown in Elements panel in DevTools
Shadow DOM is shown in the “Elements” panel in DevTools

In order to create a shadow DOM, all we have to do is call attachShadow on a DOM element:

Copied to clipboard!
document.querySelector('h1').attachShadow({ mode: 'open' });

The mode can be either open or closed. If we choose

  • open: We can access the shadow DOM with JavaScript in the context of our main document.
  • closed: We won’t be able to access the shadow DOM from the outside.
Shadow DOM properties
Shadow DOM can be either open or closed

As we can see, this is not the actual DOM our browser renders, but only a part of it. It's always attached to a regular DOM node. Also, note that if we specify the mode to be “closed”, then we won’t be able to access it via JavaScript.


So What is the DOM, Actually?

To summarize, the Document Object Model — or DOM for short — is an interface to the HTML documents we write. It's a tree-structured model that is made up of nodes. Each node in the tree is an object, representing each of our HTML elements.

Essentially, it's an API for our document that we and other programs can use to read and write every aspect of it. If you'd like to learn more about HTML, be sure to check out the following roadmap:

HTML Roadmap
  • twitter
  • facebook
HTML
Did you find this page helpful?
đź“š More Webtips
Frontend Course Dashboard
Master the Art of Frontend
  • check Access 100+ interactive lessons
  • check Unlimited access to hundreds of tutorials
  • check Prepare for technical interviews
Become a Pro

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.