Skip to content

Reading and Changing Text Content

Once you have a reference to an element, you can read what is inside it and replace it with new content. The two main properties for this are textContent and innerHTML.

textContent reads or sets the plain text content of an element. All HTML tags are stripped — you see only the text:

const heading = document.querySelector('h1');
console.log(heading.textContent); // 'Summit Trail Outfitters'

Setting textContent replaces everything inside the element with the new text:

const priceEl = document.querySelector('.tour-price');
priceEl.textContent = '$149.00';

If the new string contains HTML characters like <, they are treated as literal text — not rendered as tags. This makes textContent safe for user-generated content.

innerHTML reads or sets the HTML content of an element. Tags in the string are parsed and rendered:

const card = document.querySelector('.tour-card');
console.log(card.innerHTML); // returns the full HTML inside the element
card.innerHTML = '<h3>Cascade Ridge Hike</h3><p>$149.00</p>';

innerHTML is powerful for inserting markup — but it comes with a significant risk.

Never use innerHTML with untrusted user input. If a user submits text containing <script> tags or malicious HTML attributes, and you insert that text with innerHTML, the browser executes it. This attack is called Cross-Site Scripting (XSS).

// Dangerous — do not do this
const userInput = '<img src=x onerror="stealCookies()">';
container.innerHTML = userInput; // the onerror handler runs

The rule is simple: use innerHTML only with strings you wrote yourself or that come from your own trusted data source. Use textContent for anything that comes from user input.

innerText is similar to textContent but respects CSS visibility. Hidden elements (via display: none or visibility: hidden) are excluded from innerText but included in textContent.

const el = document.querySelector('.tour-card');
console.log(el.textContent); // includes all text including hidden elements
console.log(el.innerText); // only text visible to the user

In most cases textContent is what you need. Reach for innerText when you specifically want the user-visible text, matching what getComputedStyle would show.

PropertyWhen to use
textContentReading or setting plain text. Always safe. Default choice.
innerHTMLInserting HTML markup you control. Never with user input.
innerTextWhen you need only the visible text, respecting CSS hide/show.

This is where Module 04 helper functions connect to the DOM. Instead of a static price string, compute it:

const formatPrice = price => '$' + price.toFixed(2);
const priceEl = document.querySelector('.tour-price');
if (priceEl) {
priceEl.textContent = formatPrice(149); // '$149.00'
}

On the STO site in the Console:

// Read text content of the first h1
const heading = document.querySelector('h1');
console.log(heading.textContent);
// Update a price display
const formatPrice = price => '$' + price.toFixed(2);
const priceEl = document.querySelector('.tour-price');
if (priceEl) {
console.log('Before:', priceEl.textContent);
priceEl.textContent = formatPrice(149);
console.log('After:', priceEl.textContent);
}
// Observe the XSS risk — read only, do not run in production
// Try inserting markup with innerHTML on a non-critical element
const testEl = document.querySelector('footer');
if (testEl) {
testEl.innerHTML = '<strong>Updated via innerHTML</strong>';
}

Verify the changes visually in the browser, then reload to reset the page to its original state.

  • textContent reads or sets plain text. All HTML tags are stripped. Safe for user-generated content. Default choice.
  • innerHTML reads or sets HTML markup. Tags are parsed and rendered. Never use with untrusted user input — XSS risk.
  • innerText returns only user-visible text, respecting CSS visibility. Use when you need the rendered result.
  • Rule of thumb: textContent for plain text, innerHTML for trusted HTML markup you control.