Table of Contents

Introduction

JavaScript provides several ways to add HTML content to a web page. Two commonly used approaches are the innerHTML property and the document.createElement() method. Both can change the content displayed inside an element, but they work differently and have important differences in security, flexibility, and performance.

Understanding JavaScript innerHTML vs createElement() helps you choose an appropriate method when building dynamic interfaces, adding elements to the DOM, or updating existing page content.

What Is innerHTML in JavaScript?

The innerHTML property gets or sets the HTML markup contained inside an element. When you assign a string to innerHTML, the browser parses that string as HTML and replaces the element’s existing child content with the newly created DOM nodes.

Syntax:

element.innerHTML = "HTML content";

Example: Add HTML using innerHTML

<div id="message"></div>
<script>
  const message = document.getElementById("message");
  message.innerHTML = "<h2>Hello JavaScript</h2>" +
                      "<p>This paragraph was added with innerHTML.</p>";
</script>

The browser parses the assigned string and creates an h2 element and a p element inside the div. The original child nodes of the target element are replaced.

What Is createElement() in JavaScript?

The document.createElement() method creates a new HTML element node. The new element is created in memory and does not appear in the document until you insert it into the DOM, for example with appendChild() or append().

Syntax:

const element = document.createElement("tagName");

Example: Add HTML using createElement()

<div id="message"></div>
<script>
  const message = document.getElementById("message");

  const heading = document.createElement("h2");
  heading.textContent = "Hello JavaScript";

  const paragraph = document.createElement("p");
  paragraph.textContent = "This paragraph was added with createElement().";

  message.append(heading, paragraph);
</script>

JavaScript creates each element separately, assigns its text, and appends the nodes to the target container. The elements are not inserted until the final append() call.

JavaScript innerHTML vs createElement(): Key Differences

The main difference is how each approach creates DOM content. innerHTML parses an HTML string, while createElement() creates individual element nodes through the DOM API.

Feature innerHTML createElement()
Input HTML string Element tag name
How it works Parses markup and replaces child content Creates a node that can be configured and inserted
Text content HTML is parsed as markup Use textContent for plain text
Adding attributes Can include attributes in the HTML string Use setAttribute() or element properties
Existing child nodes Assignment replaces existing child nodes Appending adds nodes without replacing existing children
Security Can introduce cross-site scripting when unsafe strings are parsed Safer for plain text when combined with textContent
Best suited to Trusted, already-sanitized HTML fragments Building elements and inserting dynamic data as text

Adding Dynamic Data with innerHTML

You can combine variables with an HTML string to generate markup. This can be convenient when the HTML structure is fixed and every inserted value is trusted or properly sanitized.

const productName = "Laptop";
const price = 750;
const product = document.getElementById("product");

product.innerHTML = "<h3>" + productName + "</h3>" +
                    "<p>Price: $" + price + "</p>";

String concatenation can generate the markup, but do not insert untrusted user input directly into an innerHTML string. The browser interprets the string as markup, so attacker-controlled input could create executable HTML or script-capable attributes.

Adding Dynamic Data with createElement()

With createElement(), you can create the structure and set dynamic values separately. Use textContent for text instead of treating data as HTML.

const productName = "Laptop";
const price = 750;
const product = document.getElementById("product");

const heading = document.createElement("h3");
heading.textContent = productName;

const priceText = document.createElement("p");
priceText.textContent = "Price: $" + price;

product.append(heading, priceText);

This approach keeps the element structure separate from the data. The browser treats values assigned through textContent as text, so characters such as angle brackets are displayed rather than interpreted as HTML.

Security: Avoid Cross-Site Scripting (XSS)

Security is one of the most important considerations in the innerHTML vs createElement() comparison. Assigning untrusted input to innerHTML can create a cross-site scripting (XSS) vulnerability. User-submitted comments, profile names, or search terms should not be inserted into an HTML string without appropriate sanitization.

Risky example:

const userInput = getUserInput();
document.getElementById("output").innerHTML = userInput;

If the input contains malicious markup, the browser may interpret it as HTML. A safer approach for displaying plain text is:

const userInput = getUserInput();
const output = document.getElementById("output");
const paragraph = document.createElement("p");

paragraph.textContent = userInput;
output.replaceChildren(paragraph);

Using textContent prevents the input from being parsed as HTML. If an application genuinely needs to display user-provided rich HTML, use a reputable HTML sanitization library and follow a strict allowlist. Do not rely on manually removing a few dangerous tags.

Updating Existing Content

Assigning a new value to innerHTML replaces all existing child nodes of the target element. This can remove event listeners attached directly to those child nodes and discard their current state.

const list = document.getElementById("list");
list.innerHTML = "<li>New item</li>";

By contrast, appending a newly created element leaves existing child nodes in place:

const list = document.getElementById("list");
const item = document.createElement("li");

item.textContent = "Another item";
list.appendChild(item);

If you intend to replace all children with nodes you created yourself, methods such as replaceChildren() make that operation explicit. Choose the operation that matches whether you want to replace or extend the current DOM structure.

Performance Considerations

Neither method is automatically faster in every situation. The cost depends on the amount of markup, how often the DOM is updated, and whether existing nodes must be replaced. Setting innerHTML can be concise for a sizeable trusted HTML fragment, but parsing the string and replacing children may require more work than updating a small part of the DOM.

Creating many elements one by one can also involve repeated DOM operations. For a large list, build the nodes in a DocumentFragment and append the fragment once:

const list = document.getElementById("list");
const fragment = document.createDocumentFragment();
const names = ["HTML", "CSS", "JavaScript"];

names.forEach((name) => {
  const item = document.createElement("li");
  item.textContent = name;
  fragment.appendChild(item);
});

list.appendChild(fragment);

A document fragment lets you prepare several nodes before inserting them into the live document. For real applications, measure performance with representative data instead of assuming one method is always faster.

Common Mistakes to Avoid

  • Using innerHTML with untrusted input: This can expose the page to XSS. Use textContent for plain text or sanitize rich HTML with a trusted library.
  • Forgetting to insert a created element: createElement() only creates a node. Call append(), appendChild(), or another insertion method to display it.
  • Replacing content unintentionally: Assigning to innerHTML removes the target element’s existing children. Use append methods when you need to preserve them.
  • Confusing textContent with innerHTML: textContent inserts plain text, while innerHTML parses HTML markup.
  • Rebuilding nodes unnecessarily: Replacing elements can discard direct event listeners and state. Update existing nodes when that better fits the task.

Combining createElement() with DOM Methods

The DOM API includes methods that work naturally with createElement(). You can set classes with classList, assign attributes with setAttribute(), add event listeners with addEventListener(), and insert nodes with append() or prepend().

const button = document.createElement("button");

button.textContent = "Click Me";
button.classList.add("action-button");
button.setAttribute("type", "button");

button.addEventListener("click", () => {
  alert("Button clicked!");
});

document.body.append(button);

This example demonstrates how JavaScript can create a complete interactive element without constructing an HTML string. Each property and behavior is configured through a dedicated DOM API.

Categorized in:

Javascript, Js DOM,