JavaScript innerHTML lets you read or replace the HTML markup inside an element. It is useful when you intentionally need to render a small, trusted HTML fragment, such as a formatted message or a list of links. Because the browser parses its value as HTML, handle dynamic or user-provided content with care.
What is innerHTML?
innerHTML is a property available on HTML elements. Reading it returns the element’s child markup as a string. Assigning a string replaces the current descendants with nodes parsed from that markup. The element itself stays in place while its contents change.
Syntax
// Read the HTML inside an element
const markup = element.innerHTML;
// Replace the element's contents with HTML
element.innerHTML = "<p>New content</p>";
The assigned string is parsed by the browser. Tags become elements, attributes are applied, and text becomes text nodes.
Example 1: Display formatted content
Use a template string to add a small, known HTML fragment:
<div id="announcement"></div>
<script>
const announcement = document.querySelector("#announcement");
announcement.innerHTML =
"<strong>Update:</strong> The lesson is now available.";
</script>
The browser creates a <strong> element, so “Update:” is bold. The text after it remains a regular text node.
Example 2: Render a list from trusted data
When the structure is fixed and the values are controlled by your own code, a template can make the intended markup clear:
<ul id="course-list"></ul>
<script>
const courses = ["JavaScript", "HTML", "CSS"];
const list = document.querySelector("#course-list");
list.innerHTML = courses
.map(course => `<li>${course}</li>`)
.join("");
</script>
This example turns each course name into a list item, then joins the fragments into one string before assigning it. Here the values are fixed strings in the script. If values come from visitors, an API, or another untrusted source, do not interpolate them into HTML this way.
Read markup with innerHTML
You can also inspect the markup contained inside an element:
<div id="card">
<h2>DOM Basics</h2>
<p>Practice manipulating page elements.</p>
</div>
<script>
const card = document.querySelector("#card");
console.log(card.innerHTML);
</script>
The value is a string containing the child tags and text. It does not include the outer <div id="card">. Use outerHTML if you need the element itself along with its contents.
innerHTML and security
Setting innerHTML causes the browser to parse the provided string as markup. If an attacker can influence that string, they may be able to inject unwanted HTML or script-triggering attributes. This is a common cross-site scripting (XSS) risk.
For plain text, use textContent, which displays characters literally instead of parsing them as tags:
const message = document.querySelector("#message");
message.textContent = userProvidedText;
If you need formatted content from an untrusted source, validate or sanitize it with a reputable HTML sanitizer before inserting it. Avoid treating string concatenation as a security filter.
innerHTML compared with textContent
innerHTMLreads or parses markup. Use it when you need to create a deliberate HTML structure from trusted content.textContentreads or sets plain text. It does not parse tags, so it is the better default for user-entered text and labels.insertAdjacentHTML()parses HTML at a chosen position without replacing all existing children. Its input still needs the same trust and sanitization care asinnerHTML.
innerHTML in a JavaScript DOM workflow
The innerHTML property in JavaScript is most useful when a component needs to replace a complete, known fragment of DOM markup. For a JavaScript DOM update, keep the template small, keep variable data separate from trusted markup, and choose textContent when the result should be plain text.
When to use innerHTML
innerHTML can be convenient for static templates, small fragments maintained by your application, or rendering output that has already been sanitized. For complex interfaces, creating nodes with document.createElement() can make updates more targeted and easier to reason about.
Keep in mind that replacing an element’s contents removes its existing child nodes. Any event listeners attached directly to those removed nodes are lost along with them. If you only need to change a label or message, updating a specific text node or child element avoids rebuilding the rest of the content.
