JavaScriptDOM and events

Element.innerHTML

Reads or replaces an element’s content as HTML code.

Returns
A string with the HTML code of the element’s content.
On this page

Example

#
JavaScript
const menu = document.querySelector('#menu')
console.log(menu.innerHTML)

const items = ['Courses', 'Ranking', 'Profile']
menu.innerHTML = items.map((item) => `<li>${item}</li>`).join('')

console.log(menu.children.length)
console.log(menu.innerHTML)
Console
<li>Start</li>
3
<li>Courses</li><li>Ranking</li><li>Profile</li>

Definition and usage

#

The innerHTML property returns the HTML code of all of an element’s children as a string. Assigning a new string removes the existing content, and the browser parses the text as HTML and builds new elements from it.

It’s a convenient way to insert a larger fragment, for example one built with a template literal. Keep in mind, though, that every assignment destroys the old elements along with any event handlers attached to them and any text typed into form fields. innerHTML += also rebuilds the whole content from scratch.

The biggest risk is security. Inserting text from a user through innerHTML opens the door to an XSS attack: someone could smuggle in markup with code that runs on your page. Insert external data through textContent, or build elements with createElement().

Syntax

#
Syntax
const html = element.innerHTML
element.innerHTML = htmlString

More examples

#
An assignment destroys the old elements
JavaScript
const box = document.querySelector('#box')
const oldButton = document.querySelector('#buy')

box.innerHTML += '<p>Promo: 20% off</p>'

console.log(document.querySelector('#buy') === oldButton)
console.log(oldButton.isConnected)
Console
false
false

After +=, the browser rebuilt the content from scratch. The new button looks the same, but it’s a different element, and the event handler attached to the old one stopped working.

HTML versus plain text
JavaScript
const greeting = document.querySelector('#greeting')
const userName = '<em>Jack</em>'

greeting.innerHTML = `Hi, ${userName}!`
console.log(greeting.querySelector('em') !== null)

greeting.textContent = `Hi, ${userName}!`
console.log(greeting.querySelector('em') !== null)
Console
true
false

Through innerHTML, the markup in the string becomes real elements. textContent shows it as plain text, which is why it’s safe for data from a user.

Browser support

#

Widely available

Works in all modern browsers, phones included. You can use it without worry.

  • Chrome
  • Edge
  • Firefox
  • Safari

Good practices

#
  • Never insert data from a user or an API through innerHTML without sanitizing it. Use textContent for text.
  • Avoid innerHTML += in a loop, since every step rebuilds the whole content. Build the full string first, or use insertAdjacentHTML().
  • To clear an element, element.innerHTML = "" or element.replaceChildren() is enough.

Related entries

#

Spotted a mistake or missing an example? Write to us.