4.3 Module 4 · Document Object Model (DOM)

Output to HTML

Learn how to display and update content on a web page using innerHTML, textContent, and dynamic content techniques — the core of every interactive user interface.

1

Definition

Output to HTML refers to the process of updating or displaying content inside HTML elements using JavaScript, primarily through properties like innerHTML and textContent.

These properties let you change what a user sees on the page without reloading it — updating a heading after a button click, showing a result after a calculation, or building an entire list dynamically from data.

2

Simple Way

JavaScript can change what is displayed on the page — choose the right tool based on whether you need formatting or just plain text:

innerHTML Injects HTML — tags like <b>, <ul>, <img> are rendered
textContent Injects plain text — any HTML tags are shown as literal characters, not rendered
innerText Similar to textContent but respects CSS visibility — hidden text is excluded
value Reads or sets the content of form inputs — input.value, textarea.value
3

Code Examples

Example 1 — innerHTML (Renders HTML Tags)
<p id="box1">Original text</p>

<script>
  let el = document.getElementById("box1");
  el.innerHTML = "<b>Hello <em>Aman</em>!</b>";
  // The <b> and <em> tags ARE rendered — text appears bold + italic
</script>
Live Preview
Explanation
  • innerHTML replaces the element's content with a new HTML string
  • Any HTML tags inside the string are parsed and rendered by the browser
  • You can inject entire structures — lists, tables, images — with a single assignment
Example 2 — textContent (Plain Text Only)
<p id="box2">Original text</p>

<script>
  let el = document.getElementById("box2");
  el.textContent = "<b>Hello Aman</b>";
  // The tags are NOT rendered — they appear as literal text: <b>Hello Aman</b>
</script>
Live Preview
Explanation
  • textContent treats the value as raw text — HTML tags are escaped and displayed literally
  • This makes it safe for user-provided data — no risk of injecting malicious scripts
  • It is also faster than innerHTML because no HTML parsing is required
Example 3 — Dynamic Content from an Array
<ul id="list"></ul>

<script>
  let fruits = ["Apple", "Banana", "Mango"];
  let html   = "";

  fruits.forEach(function(fruit) {
    html += "<li>" + fruit + "</li>";
  });

  document.getElementById("list").innerHTML = html;
</script>
Live Preview
Explanation
  • Build an HTML string by looping through data, then inject it all at once with innerHTML
  • This is how real apps render lists, tables, and cards from API data
  • Assigning once at the end is more efficient than calling innerHTML += inside the loop
Example 4 — Reading Content & Input Value
<p id="msg">Hello World</p>
<input id="nameIn" type="text" value="Aman">

<script>
  // Reading existing content
  let para  = document.getElementById("msg");
  console.log(para.textContent);   // "Hello World"
  console.log(para.innerHTML);     // "Hello World" (same if no inner tags)

  // Reading an input's value
  let input = document.getElementById("nameIn");
  console.log(input.value);        // "Aman"

  // Writing — update the paragraph dynamically
  para.innerHTML = "<strong>Updated: " + input.value + "</strong>";
</script>
Live Preview
Explanation
  • textContent and innerHTML can both read existing content — not just write it
  • input.value reads (or sets) what's currently in an input field — not the HTML attribute, the live value
  • Combining reading and writing lets you build interactive feedback loops
4

Real-Life Example

Think of a notice board at a school:

innerHTML
Pasting a formatted poster — bold headings, colours, and images all render
textContent
Writing with a marker — plain text only, no formatting possible
value
Reading what a student wrote on the answer sheet — the live input content
Dynamic
Auto-printing a new notice for each student from a list — one template, many results
5

HTML + JavaScript Example

Click ▶ Preview and try all three buttons — each demonstrates a different way to update content: plain text, HTML, and a dynamically generated list.

Live in Browser — Dynamic Content Update
<!DOCTYPE html>
<html>
<head><title>Output to HTML</title></head>
<body style="font-family:sans-serif;padding:24px;background:#f8f9fa">

  <h2 id="title">Original Title</h2>
  <p id="content">Original content paragraph.</p>
  <ul id="list"></ul>

  <div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:12px">
    <button onclick="changeText()"
      style="padding:8px 14px;background:#f7df1e;border:none;border-radius:6px;
             cursor:pointer;font-weight:700">
      Change Text
    </button>
    <button onclick="changeHTML()"
      style="padding:8px 14px;background:#82aaff;border:none;border-radius:6px;
             cursor:pointer;font-weight:700;color:#111">
      Inject HTML
    </button>
    <button onclick="buildList()"
      style="padding:8px 14px;background:#4ade80;border:none;border-radius:6px;
             cursor:pointer;font-weight:700;color:#111">
      Build List
    </button>
    <button onclick="resetAll()"
      style="padding:8px 14px;background:#f87171;border:none;border-radius:6px;
             cursor:pointer;font-weight:700;color:#fff">
      Reset
    </button>
  </div>

  <script>
    function changeText() {
      // textContent — safe, no HTML rendering
      document.getElementById("title").textContent = "Updated with textContent";
      document.getElementById("content").textContent =
        "<b>This tag is NOT rendered</b> — shown as plain text.";
    }

    function changeHTML() {
      // innerHTML — HTML is parsed and rendered
      document.getElementById("title").innerHTML =
        "Updated with <span style='color:#e07b00'>innerHTML</span>";
      document.getElementById("content").innerHTML =
        "<b>This tag IS rendered</b> — text is bold!";
    }

    function buildList() {
      let items = ["JavaScript", "HTML", "CSS", "DOM"];
      let html  = "";
      items.forEach(item => html += "<li>" + item + "</li>");
      document.getElementById("list").innerHTML = html;
    }

    function resetAll() {
      document.getElementById("title").textContent   = "Original Title";
      document.getElementById("content").textContent = "Original content paragraph.";
      document.getElementById("list").innerHTML      = "";
    }
  </script>

</body>
</html>
Live Preview
6

Tasks (Practice)

Easy Task 1 — Update a paragraph
Starter code
<p id="para">Click the button to change me.</p>
<button onclick="updatePara()">Update</button>

<script>
  function updatePara() {
    // use textContent to change the paragraph text
  }
</script>
  • Use textContent to change the paragraph to "Text updated successfully!"
  • Run it a second time using innerHTML with a <b> tag — observe the difference
  • Set the paragraph back to empty using textContent = ""
Medium Task 2 — Bold welcome message on click
Starter code
<div id="output"></div>
<button onclick="showWelcome()">Show Welcome</button>

<script>
  function showWelcome() {
    // Use innerHTML to inject bold welcome text
  }
</script>
  • Use innerHTML to display "<b>Welcome Aman</b>" — confirm the bold renders
  • Build a list of 3 subjects using a loop and set it with one innerHTML assignment
  • Add a second button that clears the output using textContent = ""
7

MCQs

Q1
Which property renders HTML tags inside an element?
<p id="t"></p>
<script>
  document.getElementById("t").innerHTML = "<b>Bold!</b>";
</script>
Live Preview
  • A textContent
  • B innerText
  • C innerHTML
  • D value
💡 C is correct. innerHTML parses the assigned string as HTML, so <b>Bold!</b> renders as bold text. textContent would show the literal string <b>Bold!</b> as plain characters.
Q2
Which property shows raw text without rendering any tags?
<p id="u"></p>
<script>
  document.getElementById("u").textContent = "<b>Bold?</b>";
</script>
Live Preview
  • A innerHTML
  • B textContent
  • C style
  • D className
💡 B is correct. textContent treats the value as raw text and escapes any HTML characters. The output is the literal string <b>Bold?</b> — tags visible, nothing bold.
Q3
What will this display on the page?
<div id="v"></div>
<script>
  document.getElementById("v").textContent = "<h1>Hello</h1>";
</script>
Live Preview
  • A A large heading: Hello
  • B Error
  • C The literal text: <h1>Hello</h1>
  • D Nothing
💡 C is correct. textContent escapes angle brackets, so < becomes &lt; and > becomes &gt; in the DOM. The browser shows the raw tag text — not a rendered heading.
8

Pro Tips & Extra Knowledge

  • 01

    Never use innerHTML with user-provided input — it opens an XSS (Cross-Site Scripting) vulnerability. Always use textContent for user data:

    innerHTML XSS risk — use textContent instead
    <input id="userInput" type="text" value="<img onerror=alert(1) src=x>">
    <p id="safe"></p>
    <p id="unsafe"></p>
    
    <script>
      let data = document.getElementById("userInput").value;
    
      // ✓ Safe — tag is treated as text, no script runs
      document.getElementById("safe").textContent = data;
    
      // ✗ Risky — if data contains a script tag, it executes
      document.getElementById("unsafe").innerHTML = data;
    </script>
    Live Preview
  • 02

    Build the entire HTML string in a variable first, then assign it once — this is far more efficient than appending to innerHTML inside a loop:

    Build once, inject once
    <ul id="items"></ul>
    <script>
      let names = ["Alice", "Bob", "Carol", "Dave"];
    
      // ✗ Slow — reads and rewrites innerHTML on every iteration
      // names.forEach(n => document.getElementById("items").innerHTML += "<li>" + n + "</li>");
    
      // ✓ Fast — builds string first, one DOM write at the end
      let html = names.map(n => "<li>" + n + "</li>").join("");
      document.getElementById("items").innerHTML = html;
    </script>
    Live Preview
  • 03

    To clear an element's content, set textContent = "" — it is faster and safer than innerHTML = "" because it removes all nodes without HTML parsing:

    Clearing content safely
    let el = document.getElementById("output");
    
    // ✓ Preferred — no HTML parsing overhead
    el.textContent = "";
    
    // Also works but slightly slower:
    el.innerHTML = "";
    Output
    Click ▶ Run to execute
  • 04

    Use template literals for clean multi-part HTML strings — they are far more readable than concatenating with +:

    Template literals for HTML strings
    let name  = "Aman";
    let score = 95;
    let grade = "A+";
    
    // Old way — messy
    let html1 = "<h3>" + name + "</h3><p>Score: " + score + " | Grade: " + grade + "</p>";
    
    // Modern way — clean and readable
    let html2 = `<h3>${name}</h3><p>Score: ${score} | Grade: ${grade}</p>`;
    
    console.log(html2);
    Output
    Click ▶ Run to execute
Mini Challenge

One uses innerHTML, one uses textContent — predict exactly what the user sees for each, then check in the preview.

What appears on screen?
<p id="a"></p>
<p id="b"></p>

<script>
  document.getElementById("a").innerHTML    = "<b>Hello</b>";
  document.getElementById("b").textContent = "<b>Hello</b>";
</script>
Live Preview
Step-by-Step Explanation
// Both elements receive the same string: "<b>Hello</b>"

// Element #a — innerHTML
//   The browser PARSES the string as HTML
//   <b> is a valid tag → it is rendered
//   User sees: Hello   ← bold text

// Element #b — textContent
//   The browser treats the string as RAW TEXT
//   <b> and </b> are escaped to &lt;b&gt; and &lt;/b&gt;
//   User sees: <b>Hello</b>   ← literal characters, not bold

// Final visual output:
//   #a: Hello        ← BOLD (HTML rendered)
//   #b: <b>Hello</b> ← PLAIN TEXT (tags shown as characters)

// Key rule to remember:
//   innerHTML → interpret as HTML markup
//   textContent → interpret as safe plain text