DOM Tips and Techniques: Parent, Child, and Siblings

Share this article

Complex, markup-heavy web apps are the norm nowadays. A library like jQuery with its ease of use, cross-browser compatibility, and variety of features can help immensely when manipulating HTML on the fly. So it’s no wonder that a lot of developers choose to use such a library rather than native DOM APIs which have been historically quite problematic. Although browser differences are still an issue, the DOM is in much better shape today than it was 5 or 6 years ago when jQuery was really starting to take off.

In this post I’ll discuss and demonstrate a number of different DOM features that can be used to manipulate HTML, with a specific focus on parent, child, and sibling node relationships.

I’ll cover browser support in the conclusion, but keep in mind that a library like jQuery is still generally considered a good option, due to the bugs and inconsistencies in using these kinds of native features.

Counting Child Nodes

Let’s use the following HTML, which I’ll be revisiting in various forms throughout this article:

<body>
  <ul id="myList">
    <li>Example one</li>
    <li>Example two</li>
    <li>Example three</li>
    <li>Example four</li>
    <li>Example five</li>
    <li>Example Six</li>
  </ul>
</body>

If I want to count how many elements are inside the <ul> element, there are two ways I can do that.

var myList = document.getElementById('myList');

console.log(myList.children.length); // 6
console.log(myList.childElementCount); // 6

See the Pen Counting Child Elements: children & childElementCount by SitePoint (@SitePoint) on CodePen.

The logs in the last two lines produce the same result, but each with a different technique. In the first case, I’m using the children property. This read-only property returns a collection of the HTML elements inside the element being queried and I’m using the length property to find out how many are in the collection.

In the second example I’m using childElementCount, which I think is a cleaner and potentially more maintainable way of doing this (in other words, revisiting this code later, you would likely not have any trouble figuring out what childElementCount is doing).

Interestingly, I can also use childNodes.length (instead of children.length), but notice the result:

var myList = document.getElementById('myList');
console.log(myList.childNodes.length); // 13

See the Pen Counting Child Nodes with childNodes.length by SitePoint (@SitePoint) on CodePen.

This returns 13 because childNodes is a collection of all nodes, including whitespace nodes – so keep that in mind if you require the ability to differentiate between all child nodes and all element nodes.

Checking the Existence of Child Nodes

I can also use the hasChildNodes() method to check if a given element has any child nodes. This method returns a Boolean to indicate whether it has child nodes or not:

var myList = document.getElementById('myList');
console.log(myList.hasChildNodes()); // true

See the Pen hasChildNodes() by SitePoint (@SitePoint) on CodePen.

I know my list has child nodes, but I can alter the HTML to remove the elements inside the list so my HTML looks like this:

<body>
  <ul id="myList">
  </ul>  
</body>

Here’s the result if I run hasChildNodes() again:

console.log(myList.hasChildNodes()); // true

See the Pen hasChildNodes() on empty element with white space by SitePoint (@SitePoint) on CodePen.

Notice it still logs true. Although the list doesn’t contain any elements, it does contain whitespace, which is a valid type of node. This particular method deals with nodes in general, not just element nodes. To ensure hasChildNodes() returns false, my HTML would have to look like this:

<body>
  <ul id="myList"></ul>  
</body>

Now I get the expected result from my log:

console.log(myList.hasChildNodes()); // false

See the Pen hasChildNodes() on empty element with no white space by SitePoint (@SitePoint) on CodePen.

Of course, if I know I’m dealing with potential whitespace, I could first check for the existence of child nodes, then determine if any of them are element nodes using the nodeType property.

Adding and Removing Child Elements

There are techniques we can use to add or remove nodes from the DOM. The most familiar, often used in conjunction with createElement(), is the appendChild() method:

var myEl = document.createElement('div');
document.body.appendChild(myEl);

In this case I’m creating a <div> using createElement(), then I’m appending it to the body. Pretty straightforward, and it’s likely you’ve used that technique before.

But instead of inserting a newly-created element, I could also use appendChild() as a simple means of moving an existing element. Let’s say I have the following HTML:

<div id="c">
  <ul id="myList">
    <li>Example one</li>
    <li>Example two</li>
    <li>Example three</li>
    <li>Example four</li>
    <li>Example five</li>
    <li>Example Six</li>
  </ul>
  <p>Example text</p>
</div>

I can change the location of the list using the following code:

var myList = document.getElementById('myList'),
    container = document.getElementById('c');

container.appendChild(myList);

The resulting DOM will look like this:

<div id="c">
  <p>Example text</p>
  <ul id="myList">
    <li>Example one</li>
    <li>Example two</li>
    <li>Example three</li>
    <li>Example four</li>
    <li>Example five</li>
    <li>Example Six</li>
  </ul>
</div>

See the Pen Using appendChild() to change an element’s location by SitePoint (@SitePoint) on CodePen.

Notice that the entire list was removed from its spot (above the paragraph) and then appended to the end of the body, placing it below the paragraph. So although you’ll commonly see appendChild() used to add elements produced using the createElement() method, it’s also an easy way to move an existing element to another location on the page.

I can also remove a child completely from the DOM using removeChild(). Here’s how I can remove the same list element from the previous HTML snippet:

var myList = document.getElementById('myList'),
    container = document.getElementById('c');

container.removeChild(myList);

See the Pen Using removeChild() by SitePoint (@SitePoint) on CodePen.

Now the element is removed. The removeChild() method returns the removed element, so I can store it somewhere if I need to do so for later use:

var myOldChild = document.body.removeChild(myList);
document.body.appendChild(myOldChild);

See the Pen Using removeChild() to move an element by SitePoint (@SitePoint) on CodePen.

There’s also the ChildNode.remove() method, which is a newer feature in the spec:

var myList = document.getElementById('myList');
myList.remove();

See the Pen Using childNode.remove() by SitePoint (@SitePoint) on CodePen.

This method doesn’t return the removed object and doesn’t work in Internet Explorer (only Edge). I should also note that both of these removal techniques will target text nodes as well as elements.

Replacing Child Elements

I can replace an existing child with a new child, whether that new child exists somewhere already, or I’ve created it from scratch. Here’s the HTML:

<p id="par">Example Text</p>

And then the JavaScript:

var myPar = document.getElementById('par'),
    myDiv = document.createElement('div');

myDiv.className = 'example';
myDiv.appendChild(document.createTextNode('New element text'));
document.body.replaceChild(myDiv, myPar);

See the Pen Using replaceChild() by SitePoint (@SitePoint) on CodePen.

Here I’m creating the element, appending a text node with createTextNode(), then inserting it into the page in place of the paragraph element. The previous paragraph element is then replaced with the following HTML:

<div class="example">New element text</div>

As you can see, the replaceChild() method takes two arguments: The new element and the old element that’s being replaced.

I can also use this method to move an existing element from its place and put it in place of a new one. Look at the following HTML:

<p id="par1">Example text 1</p>
<p id="par2">Example text 2</p>
<p id="par3">Example text 3</p>

I can replace the third paragraph with the first paragraph using the following code:

var myPar1 = document.getElementById('par1'),
    myPar3 = document.getElementById('par3');

document.body.replaceChild(myPar1, myPar3);

Now the generated DOM will look like this:

<p id="par2">Example text 2</p>
<p id="par1">Example text 1</p>

See the Pen Using replaceChild() to swap one element for another by SitePoint (@SitePoint) on CodePen.

Targeting Specific Child Elements

There are a few different ways to target specific elements. As seen earlier, I can use the children collection or the childNodes property, and then work from there. But let’s see a few other options.

The firstElementChild and lastElementChild properties do exactly what their names’ suggest: they target the first and last child elements for a specified parent. Let’s go back to our HTML list:

<body>
  <ul id="myList">
    <li>Example one</li>
    <li>Example two</li>
    <li>Example three</li>
    <li>Example four</li>
    <li>Example five</li>
    <li>Example Six</li>
  </ul>
</body>

I can target the first or last elements in this list with the following:

var myList = document.getElementById('myList');
console.log(myList.firstElementChild.innerHTML); // "Example one"
console.log(myList.lastElementChild.innerHTML); // "Example six"

See the Pen Using firstElementChild and lastElementChild by SitePoint (@SitePoint) on CodePen.

I can also use the previousElementSibling and nextElementSibling properties if I want to target child elements other than the first or last. These can be used in conjunction with firstElementChild and lastElementChild:

var myList = document.getElementById('myList');
console.log(myList.firstElementChild.nextElementSibling.innerHTML); // "Example two"
console.log(myList.lastElementChild.previousElementSibling.innerHTML); // "Example five"

See the Pen Using nextElementSibling and previousElementSibling by SitePoint (@SitePoint) on CodePen.

There are also the similar firstChild, lastChild, previousSibling, and nextSibling properties, but those properties deal with all types of nodes, not just element nodes. In many cases element-specific properties are going to be more useful because they only target element nodes.

Injecting Content into the DOM

I’ve already looked at ways to add elements to the DOM. Let’s address a similar concept, and look at a few features that give you more fine-grained control over where you insert content.

First, there’s the straightforward insertBefore() method. This works much like replaceChild(), taking two arguments and it will work with a newly-created element or an existing one. Let’s use the following HTML:

<div id="c">
  <ul id="myList">
    <li>Example one</li>
    <li>Example two</li>
    <li>Example three</li>
    <li>Example four</li>
    <li>Example five</li>
    <li>Example Six</li>
  </ul>
  <p id="par">Example Paragraph</p>
</div>

Notice the paragraph element. I’m going to remove the paragraph, then insert it before the list, all in one fell swoop:

var myList = document.getElementById('myList'),
    container = document.getElementBy('c'),
    myPar = document.getElementById('par');

container.insertBefore(myPar, myList);

See the Pen Using insertBefore() by SitePoint (@SitePoint) on CodePen.

The resulting HTML will have the paragraph element before the list, instead of after, which is yet another way to move an element from its existing spot to another place in the page:

<div id="c">
  <p id="par">Example Paragraph</p>
  <ul id="myList">
    <li>Example one</li>
    <li>Example two</li>
    <li>Example three</li>
    <li>Example four</li>
    <li>Example five</li>
    <li>Example Six</li>
  </ul>
</div>

As with replaceChild(), insertBefore() takes two arguments: the element that’s being added and the element before which we want to add the element specified in the first argument.

That method is fairly straightforward. Let’s now use a much more powerful method to get more precise with these insertions: the insertAdjacentHTML() method.

var myEl = document.getElementById('el');
myEl.insertAdjacentHTML('beforebegin', '<p>New element</p>');

The above code will insert the specified string of content before the targeted element (in this case, before the list). The second argument is the string of HTML that you want to insert (this could also just be text with no HTML tags). The first argument, also represented as a string, has to be one of the following four values:

  • ‘beforebegin’ – Inserts the string before the specified element
  • ‘afterbegin’ – Inserts the string inside the specified element, before its first child
  • ‘beforeend’ – Inserts the string inside the specified element, after its last child
  • ‘afterend’ – Inserts the string after the specified element

To make it easier to understand what each of these values represents, look at the HTML comments in the following snippet. Assuming the #el div is the targeted element, each comment indicates where the HTML would go with the specified value for the first argument:

<!-- beforebegin -->
<div id="el">
  <!-- afterbegin -->
  <p>Some example text</p>
  <!-- beforeend -->
</div>
<!-- afterend -->

That should make it fairly clear what each of the possible values do with the string of content.

See the Pen Using insertAdjacentHTML() by SitePoint (@SitePoint) on CodePen.

Browser Support

When discussing anything in the DOM, browser support is always a big factor. Bugs aside, below is a rundown of how well these features are supported.

The following features are supported in all browsers, including old versions of IE:

The following features are supported in IE9+ and all other browsers:

That leaves only the Node.remove() method, which, as mentioned, has no support in Internet Explorer, but has been added to Microsoft’s new Edge browser.

So overall, browser support for these DOM features is excellent. Of course, there will be bugs and interoperability issues, so make sure you do thorough testing if you decide to make heavy use of any of these.

Conclusion

Ideally, the JavaScript language and the native DOM APIs should be enough to allow us to build stuff easily and in a cross-browser manner. Eventually I think we will get to that point, but in the meantime, tools like jQuery will continue to fill this need.

Feel free to comment on any related features that you’ve discovered or used when attempting to manipulate HTML on the fly with native DOM scripting.

Frequently Asked Questions (FAQs) about DOM Tips and Techniques: Parent, Child, and Siblings

What is the Document Object Model (DOM) in web development?

The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the structure of a document and allows a way to manipulate the content and structure. The DOM represents a document as a tree structure where each node is an object representing a part of the document. The nodes can be manipulated by using methods and properties provided by the DOM API.

How does the parent-child relationship work in the DOM?

In the DOM, elements are related to each other in a hierarchical structure, similar to a family tree. The parent-child relationship is one of the most important relationships. A parent element is an element that has other elements nested inside it. These nested elements are known as child elements. For example, in HTML, a <div> element containing <p> elements would be the parent, and the <p> elements would be the children.

What are sibling elements in the DOM?

Sibling elements in the DOM are elements that share the same parent. For example, if you have a <div> element that contains multiple <p> elements, those <p> elements are siblings because they are all direct children of the same <div> element.

How can I select child elements in the DOM?

You can select child elements in the DOM using various methods. One common method is using the children property, which returns a live HTMLCollection of child elements. For example, if you have a parent element stored in a variable parentElement, you can access its children with parentElement.children.

How can I traverse from a child to its parent in the DOM?

You can traverse from a child to its parent in the DOM using the parentNode property. This property returns the parent of the specified node in the DOM tree. For example, if you have a child node stored in a variable childNode, you can access its parent with childNode.parentNode.

How can I select sibling elements in the DOM?

You can select sibling elements in the DOM using the nextSibling and previousSibling properties. These properties return the next and previous sibling of the specified node in the DOM tree, respectively. For example, if you have a node stored in a variable node, you can access its next sibling with node.nextSibling and its previous sibling with node.previousSibling.

What is the difference between children and childNodes in the DOM?

The children property returns a collection of an element’s child elements, as an HTMLCollection object. On the other hand, the childNodes property returns a collection of an element’s child nodes, as a NodeList object. The key difference is that children only includes element nodes, while childNodes includes all node types, such as text nodes and comment nodes.

How can I add a new child element in the DOM?

You can add a new child element in the DOM using the appendChild() method. This method adds a node to the end of the list of children of a specified parent node. If the given child is a reference to an existing node in the document, appendChild() moves it from its current position to the new position.

How can I remove a child element in the DOM?

You can remove a child element in the DOM using the removeChild() method. This method removes a child node from the DOM and returns the removed node. The removed child node still exists in memory, but is no longer part of the DOM.

How can I replace a child element in the DOM?

You can replace a child element in the DOM using the replaceChild() method. This method replaces a child node within the given parent node. The replaced child node is returned by the method. If the new node already exists in the DOM, it is removed from its original position and inserted in the new position.

Louis LazarisLouis Lazaris
View Author

Louis is a front-end developer, writer, and author who has been involved in the web dev industry since 2000. He blogs at Impressive Webs and curates Web Tools Weekly, a newsletter for front-end developers with a focus on tools.

DOMdom apiLouisL
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week