One of the most unique and useful abilities of JavaScript is its ability to manipulate the web pages. It can manipulate both the HTML and CSS of any web page through the DOM. But what is the DOM, and how do we go about changing it? Let’s jump right in…
Watch An Introduction to Browser Rendering.
Duration: 8 minutes
Read: What, exactly, is the DOM?
The DOM (or Document Object Model) is a tree-like representation of the contents of a webpage – a tree of "nodes" with different relationships depending on how they’re arranged in the HTML document.
<div id="container">
<div class="display"></div>
<div class="controls"></div>
</div>
In the above example, the <div class="display"></div>
is a "child" of <div id="container"></div>
and a sibling to <div class="controls"></div>
. Think of it like a family tree. <div id="container"></div>
is a parent, with its children on the next level, each on their own "branch".
When working with the DOM, you use "selectors" to target the nodes you want to work with. You can use a combination of CSS-style selectors and relationship properties to target the nodes you want. Let’s start with CSS-style selectors. In the above example, you could use the following selectors to refer to <div class="display"></div>
:
You can also use relational selectors (i.e. firstElementChild
or lastElementChild
etc.) with special properties owned by the nodes.
const container = document.querySelector('#container');
// select the #container div (don't worry about the syntax, we'll get there)
console.dir(container.firstElementChild);
// select the first child of #container => .display
const controls = document.querySelector('.controls');
// select the .controls div
console.dir(controls.previousElementSibling);
// selects the prior sibling => .display
So you’re identifying a certain node based on its relationships to the nodes around it.
When your HTML code is parsed by a web browser, it is converted to the DOM as was mentioned above. One of the primary differences is that these nodes are objects that have many properties and methods attached to them. These properties and methods are the primary tools we are going to use to manipulate our webpage with JavaScript. We’ll start with the query selectors – those that help you target nodes.
*There are several other, more specific queries, that offer potential (marginal) performance benefits, but we won’t be going over them now.
It’s important to note that when using querySelectorAll, the return value is not an array. It looks like an array, and it somewhat acts like an array, but it’s really a "nodelist". The big distinction is that several array methods are missing from nodelists. One solution, if problems arise, is to convert the nodelist into an array. You can do this with Array.from() or the spread operator.
[options]
in this case means you can add some optional parameters to the function. Don’t worry about these at this point.const div = document.createElement('div');
This function does NOT put your new element into the DOM – it simply creates it in memory. This is so that you can manipulate the element (by adding styles, classes, ids, text etc.) before placing it on the page. You can place the element into the DOM with one of the following methods.
When you have a reference to an element, you can use that reference to alter the element’s own properties. This allows you to do many useful alterations, like adding/removing and altering attributes, changing classes, adding inline style information and more.
const div = document.createElement('div');
// create a new div referenced in the variable 'div'
div.style.color = 'blue';
// adds the indicated style rule
div.style.cssText = 'color: blue; background: white';
// adds several style rules
div.setAttribute('style', 'color: blue; background: white');
// adds several style rules
See DOM Enlightenment’s section on CSS Style rules for more info on inline styles.
Note that if you’re accessing a kebab-cased css rule from JS, you’ll either need to use camelcase or you’ll need to use bracket notation instead of dot notation.
div.style.background-color // doesn't work - attempts to subtract color from div.style.background
div.style.backgroundColor // accesses the divs background-color style
div.style['background-color'] // also works
div.style.cssText = "background-color: white" // ok in a string
div.setAttribute('id', 'theDiv');
// if id exists update it to 'theDiv' else create an id
// with value "theDiv"
div.getAttribute('id');
// returns value of specified attribute, in this case
// "theDiv"
div.removeAttribute('id');
// removes specified attribute
See MDNs section on HTML Attributes for more info on available attributes.
div.classList.add('new');
// adds class "new" to your new div
div.classList.remove('new');
// remove "new" class from div
div.classList.toggle('active');
// if div doesn't have class "active" then add it, or if
// it does, then remove it
It is often standard (and more clean) to toggle a CSS style rather than adding and removing inline CSS.
div.textContent = 'Hello World!'
// creates a text node containing "Hello World!" and
// inserts it in div
div.innerHTML = '<span>Hello World!</span>';
// renders the html inside div
*Note that textContent is preferable for adding text, and innerHTML should be used sparingly as it can create security risks if misused.
Let’s take a minute to review what we’ve covered and give you a chance to practice this stuff before moving on. Check out this example of creating and appending a DOM element to a webpage.
<!-- your html file: -->
<body>
<h1>
THE TITLE OF YOUR WEBPAGE
</h1>
<div id="container"></div>
</body>
// your javascript file
const container = document.querySelector('#container');
const content = document.createElement('div');
content.classList.add('content');
content.textContent = 'This is the glorious text-content!';
container.appendChild(content);
In the JavaScript file, first we get a reference to the container
div that already exists in our HTML. Then we create a new div and store it in the variable content
. We add a class and some text to the content
div and finally append that div to container
. All in all it’s a simple process. After the JavaScript code is run, our DOM tree will look like this:
<!-- The DOM -->
<body>
<h1>
THE TITLE OF YOUR WEBPAGE
</h1>
<div id="container">
<div class="content">
This is the glorious text-content!
</div>
</div>
</body>
Keep in mind that the JavaScript does not alter your HTML, but the DOM – your HTML file will look the same, but the JavaScript changes what the browser renders.
Important note: Your JavaScript, for the most part, is run whenever the JS file is run, or when the script tag is encountered in the HTML. If you are including your JavaScript at the top of your file, many of these DOM manipulation methods will not work because the JS code is being run before the nodes are created in the DOM. The simplest way to fix this is to include your JavaScript at the bottom of your HTML file so that it gets run after the DOM nodes are parsed and created.
Plain JavaScript is a reference of JavaScript code snippets and explanations involving the DOM, as well as other aspects of JS. If you’ve already learned jQuery, it will help you figure out how to do things without it.
This W3Schools article offers simple and easy-to-understand lessons on DOM.
JS DOM Crash Course is an extensive and well explained 4 part video series on the DOM by Traversy Media.
Understanding The Dom is an aptly named article-based tutorial series by Digital Ocean.