Learn how to dynamically create HTML elements with plain JavaScript

The majority of JS frameworks uses some sort of techniques to handle or manipulate the Document Object Model (DOM) tree. The DOM makes it possible for programs such as JavaScript to change the document structure, style and content. The HTML elements on a page is simply a tree of nodes and objects that together provides structure for showing text, link, image, video and so forth.

The purpose of this article is create a list of bookmarks, and present the URLs using plain JS. The underlying purpose is to understand how things work behind the scenes, and cover one of the fundamental pillars used in modern JS frameworks such as Angular, React and Vue. So the example itself is not that difficult to achieve, but the concept is what is important.

Heads-up: In this example we use the document interface to access the DOM tree, but as Marko mentioned in the comment section, we can use another powerful interface named documentFragment. It’s a lightweight version of document that prevents layout recalculation and improves the performance when dealing with large amounts of DOM manipulation.

Not only is using DocumentFragments to append about 2700 times faster than appending with innerHTML, but it also keeps the recalculation, painting and layout to a minimum, source.

This article focuses on document interface for two reasons, (1) we are dealing with few elements, and (2) its a familiar interface among developers.

If you want to become a better web developer, start your own business, teach others, or improve your development skills, I’ll be posting weekly tips and tricks on the latest web development languages.

Here’s what we’ll address

  • Create a list of bookmarks
  • The JavaScript part
  • Create a new bookmark
  • How to access the bookmarks element (show different approaches)
  • Show list of bookmarks
  • Conclusion

Create a list of bookmarks

In this example, we are going to create a list of bookmarks, append bookmarks to parent element and then present it in HTML using plain JavaScript.

The starting point is an index.html file that consist of a div element with an ID of bookmarks. The ID is an important and necessary factor in order to locate the element so that we can manipulate it.

// File: index.html
<div id=”bookmarks”></div>
The ID is case-sensitive string which is unique within the document; only one element may have any given ID, source.

The JavaScript part

Since this is a small example, we’ve put the JS code in one file index.js. But in terms of best practice, we would separate behaviour by using classes and methods. The code for this example can be found here.

In order to create a collection of bookmarks, we’ll need a placeholder (an array). This allows us to further use array features like push, pop and shift to manipulation data. But in this example, we’ll mainly focus on the push feature for creating new bookmarks.

We’ve also defined few const variables such as childElement, appendChildElement and parentElement to make the code readable.

const bookmarks = [];
const childElement, appendChildElement, parentElement;

So the benefit of the bookmarks array is to create objects (a state of information), which we can chain with these functional JS methods like filter(), map(), reduce(), for...of and some() and so forth.

I’ve written an article that covers these useful and important methods for devs that want to improve their skills in web dev, check out.

Create a new bookmark

Now that we have an empty array, next step is to create a bookmark object with property name URL. We do this by using the push method which is used to add a new object when dealing with arrays. Notice that we use curly brackets {} to inform JS that this is an object.

There is a saying among web devs that everything in JS is an object, I haven’t really tested this myth, but I cannot quite disagree either.

So what is an object?

In JavaScript, an object is a standalone entity, with properties and type. Compare it with a cup, for example. A cup is an object, with properties. A cup has a color, a design, weight, a material it is made of, etc. The same way, JavaScript objects can have properties, which define their characteristics. 
Read more.

Alright, so back to the code, in order to add objects as mentioned earlier, we do something like this. Notice the push method we’ve chained to the bookmarks array.

// Create a new bookmark (object)
bookmarks.push({ url: 'https://facebook.com' });
bookmarks.push({ url: 'https://instagram.com' });
bookmarks.push({ url: 'https://twitter.com' });
// Outputs
[
{"url":"https://facebook.com"},
{"url":"https://instagram.com"},
{"url":"https://twitter.com"}
]

How to access the bookmarks element

Now that we have a list of bookmarks (objects), we still have couple of steps left before we can present the results in HTML.

Currently, this is what we have.

<div id="bookmarks">                
<!-- empty -->
</div>

And this is the end result we want to achieve. So the question is, what method can we use to access the parent element in order to add/append child elements?

<div id="bookmarks">                <-- parent element
<div>https://facebook.com</div> <-- child element
<div>https://instagram.com</div> <-- child element
<div>https://twitter.com</div> <-- child element
</div>

JS ecosystem provides multiple of ways to interact with the DOM tree, lets see which one fits our goal.

Option 1:
We can use the method getElementByClassName('.class-name'), but this is mostly used when we want to target multiple/similar elements at once.

Option 2:
The other option is use querySelector() or querySelectorAll(). But this is mostly relevant when we are dealing with elements that don’t have an ID or class name.

Option 3: 
The final option and most commonly one is to use getElementById('id-name') because our element has an ID of bookmarks. So for this example, we’ll be using this one.

The Document method getElementById() returns an Element object representing the element whose id property matches the specified string. Since element IDs are required to be unique if specified, they're a useful way to get access to a specific element quickly. Read more.

So to access the HTML element with ID bookmarks, and then access the object later in our application, we assign the object to parentElement variable.

parentElement = document.getElementById('bookmarks');

And then if console.log(parentElement) we get an HTMLDivElement object like which means the binding works.

HTML element object

Show list of bookmarks

Next step is to show the bookmarks URL on the page.

Since we have a list of 3 bookmarks, we can now iterate by using for...of iterator to perform DOM manipulation separately.

In each iteration, we do.

  1. Create child element
  2. Append child element to parent element
  3. Show bookmark URL in child element
// Add child elements
for (let bookmark of bookmarks) {
childElement = document.createElement('div');
appendChildElement = parentElement.appendChild(childElement)
appendChildElement.innerHTML = bookmark.url
}

So if everything works we can either see the URLs on the page, or use the debug tool to see if the elements are added properly.

The elements should be structured like this (use debug tool).

<div id="bookmarks">
<div>https://facebook.com</div>
<div>https://instagram.com</div>
<div>https://twitter.com</div>
</div>

Conclusion

It is important to understand the underlying parts of JS, and how it is used to dynamically interact with the DOM tree. One thing is to use a framework that does all of this for you automatically, another thing is to actually know what happens behind the scenes. In overall, it provides the ability to take critical decisions based on architecture and performance, which is not something most devs really want to focus on. Differences like these allows you to understand the limitation of building web apps, and what is achievable in the end.

A framework usually provides us the ability create components such as <app-product-list></app-product-list> or target an element with a unique ID such as <div id="bookmarks"></div> as we’ve done. In both ways, it is recommended to know how things work, so that you can effectively handle unexpected issues in relation to the DOM tree.



You can find me on Medium where I publish on a weekly basis. Or you can follow me on Twitter, where I post relevant web development tips and tricks along with personal stories.

P.S. If you enjoyed this article and want more like these, please clap ❤ and share with friends that may need it, it’s good karma.