How to Add an Element to the DOM?
Tags: javascript, webdev
Published: 2020-03-04 14:08:46

Nowadays,  **JavaScript frameworks**  like React or Vue have taken the "pleasure" of managing the  **DOM**  (Document Object Model) from most of the developers. So, unless you're a curious person, UI library creator, or someone who doesn't like to  **over-rely**  or use frameworks at all, you won't find this blog post useful. ;) But anyway, here are all the ways of adding an element to the DOM directly.

# Basics stuff
## Creating elements
To create a new HTML element, you have to use the  [`document.createElement()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement)  method.

```javascript
const el = document.createElement("div");
```

The method takes a string as a  **tag name**  for the element (automatically converted to lowercase), and an optional  **options**  object, which matters only for Web Components.

## Namespaces
You have to know that  `document.createElement()`  works only for the HTML elements. This means that elements from a different  **namespace**  (most notably  **SVG**-ones) won't work correctly.

To fix that issue, you have to use the  [`document.createElementNS()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS)  method, which creates an element with the specified namespace URI.

```javascript
const svg = document.createElementNS("<http://www.w3.org/2000/svg>", "svg");
```

## Movements

Now, when working with newly-created elements, adding them to the DOM works just like you might expect. But things change when working with elements that are already within DOM, e.g.

```javascript
/* HTML:
...
<body>
	<div id="app"></div>
</body>
...
*/
const el = document.querySelector("app");
```

Now, when you'll use one of the methods that we'll talk about in a second on such an element, it won't be added to the DOM, rather than simply  **moved**  to the new position.

No matter what parent it had before or how deep it was in the hierarchy, the element will be removed and added back again at the selected position.

# Appending
## [AppendChild](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild)
The simplest, most well-known method of appending an element to the DOM is certainly the  `appendChild()`.

```javascript
// ...
document.body.appendChild(el);
```

The provided element is appended at the end of the parent's children list.

## [Append](https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append)/[prepend](https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/prepend)
Now,  `appendChild()`  has been around for a long time and is supported by pretty much all the in-use browsers. But, if you're willing to give up some  **support**  for the sake of functionality, you might be interested in the newer  `append()`  and  `prepend()`  methods.

```javascript
// ...
document.body.append(el);
document.body.prepend(el2);
document.body.append("Text");
/* HTML:
<body>
	<div></div> <- el2
	<div></div> <- el
	Text
</body>
*/
```

`append()`  appends the element at the  **end**  of the parent's children list, while  `prepend()`  inserts it at the  **beginning**.

Both  `append()`  and  `prepend()`  feature the ability to insert  **strings**  directly into the DOM. For comparison, to achieve the same effect with  `appendChild()`, you'd have to explicitly create a new  [Text node](https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode):

```javascript
document.appendChild(document.createTextNode("Text"));
```

In addition to that, both  `append()`  and  `prepend()`  can accept  **multiple arguments**  and thus, insert multiple nodes at once.

```javascript
// ...
document.body.append(el, el2);
document.body.appendChild(el);
document.body.appendChild(el2);
```

Of course, all this goodness comes at a cost.  `append()`  and  `prepend()`  don't support some older browsers (e.g. no IE) and require (arguably simple)  **polyfills**.

# [InnerHTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML)
As you might know,  `innerHTML`  is a property, rather than a method. You can either read it or set it to HTML string which, will be parsed as HTML and placed into the DOM.

```javascript
document.body.innerHTML = "<div>Text</div>";
```

It seems like a pretty easy and straightforward solution, but it has some major drawbacks:

-   The value returned from the  `innerHTML`  property access doesn't have to be the same as the one you've set before, as it's based on the element's content and is generated  **dynamically**.
-   Setting  `innerHTML`  removes all previous content of the parent.
-   `innerHTML`  is bad for  **performance**  (in most cases), because of the necessity to parse the HTML string and remove all the previous nodes. However, if removing all the children is your goal, then  `innerHTML = ""`  is a safe bet.
-   Uncontrolled changes of  `innerHTML`  can lead to  **security**  issues. Although  `<script>`  blocks aren't executed when created with  `innerHTML`, there are other ways of executing possibly malicious JS code without using the  `<script>`  block (e.g. inline events listeners)

# Inserting
Insert methods, in comparison to append ones, give you more control over where you want to position your element.

## [InsertBefore](https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore)
`insertBefore()`  method allows you to insert an element right before the specified one, e.g.

```javascript
// ...
document.body.append(el);
document.body.insertBefore(el2, el);
```

The first parameter is the element to be inserted, while the second one is used as a reference. Keep in mind that while the reference should be provided, it can be equal to  `null`, in order to simply append the element at the end of the parent's children list.

While there's no  _"insertAfter"_  method or anything like that, you can achieve such an effect through the combination of the  `insertBefore()`  method with the  [`nextElementSibling`](https://developer.mozilla.org/en-US/docs/Web/API/NonDocumentTypeChildNode/nextElementSibling)  property of the reference node.

```javascript
// ...
const insertAfter = (parent, child, reference) => {
  parent.insertBefore(child, reference.nextElementSibling);
};

document.body.append(el);
insertAfter(document.body, el2, el);
```

## InsertAdjacent
Next up, we've got a bunch of  _insertAdjacent_  methods, which allow you to insert a node in one of the possible positions, in relation to the element the method was called upon (aka  **target element**).

There are 3 of these methods:

-   [`insertAdjacentElement()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement)  - for elements;
-   [`insertAdjacentHTML()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML)  - for HTML strings (like with  `innerHTML`, but is faster and doesn't remove prior content);
-   [`insertAdjacentText()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentText)  - for inserting Text nodes;

All of them have similar syntax, but can be used to insert only one specific kind of content. Take a look at the example of  `insertAdjacentElement()`  call:

```javascript
// ...
document.body.insertAdjacentElement(el, "afterbegin")
```

The first parameter is the element to be inserted, while the second one is a string indicating the  **position**  at which the element is to be inserted. There are 4 available options here:

-   `"beforebegin"`  - just before the target element;
-   `"afterbegin"`  - at the top of the target element's children tree;
-   `"beforeend"`  - at the bottom of the target element's children tree;
-   `"afterend"`  - just after the target element;

# Sibling-relative placement
In comparison to all the previous methods, the  [`after()`](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/after)  and  [`before()`](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/before)  methods rely on the  **sibling nodes**  rather than the parent itself. They can insert multiple nodes (elements and text nodes) at once and have support similar to  `append()`  or  `prepend()`.

```javascript
// ...
document.body.append(el);
el.after(el2, el3);
```

# Replacement
Lastly, if you want to insert an element in place of a previous one, i.e.  **replace**  it, you can use the  `replaceChild()`  method, together with providing the new and previous element respectively.

```javascript
// ...
document.body.append(el);
document.body.replaceChild(el2, el);
```

# There's a lot
So, these are all of the available methods for inserting a new element to the DOM (at least to my knowledge). Again, unless you're a library author or don't want to use any framework except  [Vanilla JS](http://vanilla-js.com/), then these methods won't matter to you much. However, it's still nice to know at least a little bit about what's going on  **under-the-hood**.

If you like the post consider  **sharing it**  and  **following me**  on  [Twitter](https://twitter.com/areknawo) or [Facebook](http://facebook.com/areknawoblog). If you're interested, I also recommend checking out my  [YouTube channel](https://www.youtube.com/channel/UCUw6bg379ONlG1E_oxhwi-A/). Again, thanks for reading this piece and have a nice day!