JavaScript

innerHTML & outerHTML - Get and Replace HTML Content

Guide to JavaScript innerHTML and outerHTML - reading, writing, and replacing HTML content with security and performance tips.

innerHTML

The innerHTML property gets or sets the HTML markup inside an element - everything between its opening and closing tags.

Reading innerHTML

// HTML: <div id="box"><p>Hello <strong>world</strong></p></div>

const box = document.getElementById('box');
console.log(box.innerHTML);
// Output: <p>Hello <strong>world</strong></p>

// textContent strips tags
console.log(box.textContent);
// Output: Hello world

Writing innerHTML

// Replace all content inside the element
box.innerHTML = '<h2>New Title</h2><p>Updated content</p>';

// Append HTML (preserves existing content)
box.innerHTML += '<p>Another paragraph</p>';

// Clear all content
box.innerHTML = '';

outerHTML

The outerHTML property includes the element itself - not just its children, but also its opening and closing tags.

// HTML: <div id="box" class="card"><p>Content</p></div>

const box = document.getElementById('box');

console.log(box.innerHTML);
// <p>Content</p>

console.log(box.outerHTML);
// <div id="box" class="card"><p>Content</p></div>

// Replace the entire element (including itself)
box.outerHTML = '<section id="new"><h2>Replaced</h2></section>';
// The #box div no longer exists in the DOM

innerHTML vs outerHTML Comparison

PropertyReadsWritesElement preserved?
innerHTMLChildren onlyReplaces childrenYes
outerHTMLElement + childrenReplaces entire elementNo - element is removed
textContentText only (no tags)Replaces with textYes

Security - XSS Prevention

Never insert unsanitized user input into innerHTML. This is a cross-site scripting (XSS) vulnerability:

// DANGEROUS - user input could contain scripts
const userInput = '<img src=x onerror=alert("XSS")>';
div.innerHTML = userInput; // Executes the attack!

// SAFE - use textContent for plain text
div.textContent = userInput; // Renders as harmless text

// SAFE - use DOMPurify to sanitize HTML
import DOMPurify from 'dompurify';
div.innerHTML = DOMPurify.sanitize(userInput);

// SAFE - create elements programmatically
const p = document.createElement('p');
p.textContent = userInput;
div.appendChild(p);

Performance Considerations

Every time you set innerHTML, the browser must parse the HTML string, destroy existing DOM nodes, and create new ones. This is expensive in loops:

// SLOW - re-parses entire content on each iteration
const list = document.getElementById('list');
items.forEach(item => {
  list.innerHTML += `<li>${item}</li>`;  // O(n²)
});

// FAST - build string first, assign once
let html = '';
items.forEach(item => {
  html += `<li>${item}</li>`;
});
list.innerHTML = html;  // Single DOM update

// FASTEST - use DocumentFragment
const frag = document.createDocumentFragment();
items.forEach(item => {
  const li = document.createElement('li');
  li.textContent = item;
  frag.appendChild(li);
});
list.appendChild(frag);  // Single reflow

Modern Alternatives

// insertAdjacentHTML - insert without destroying existing content
element.insertAdjacentHTML('beforeend', '<p>New paragraph</p>');

// Positions:
// 'beforebegin' - before the element
// 'afterbegin'  - inside, before first child
// 'beforeend'   - inside, after last child
// 'afterend'    - after the element

// replaceWith - replace element (like outerHTML but with nodes)
const newEl = document.createElement('section');
newEl.innerHTML = '<h2>Replacement</h2>';
oldEl.replaceWith(newEl);

// remove() - delete element from DOM
element.remove();

Practical Examples

// Dynamic list rendering
function renderList(items, containerId) {
  document.getElementById(containerId).innerHTML =
    items.map(i =>
      `<li class="item">${i.name} -$${i.price}</li>`
    ).join('');
}

// Template-based rendering
function renderCard(data) {
  return `
    <div class="card">
      <h3>${data.title}</h3>
      <p>${data.description}</p>
      <span class="tag">${data.category}</span>
    </div>`;
}

container.innerHTML = cards.map(renderCard).join('');

Last updated: 2026 • Browse all courses