Modifying Element Content

Once you have selected an element, you can change its content. The DOM gives you several properties for reading and writing content. They do not all behave the same way, so we will go through them one at a time.

textContent

The textContent property gets or sets an element’s text content:

const heading = document.querySelector("h1");

// Read text content
console.log(heading.textContent); // "Hello World"

// Set text content
heading.textContent = "Welcome!";

Setting textContent replaces all child nodes with a single text node. Any HTML in the string is displayed as plain text, not rendered:

const div = document.querySelector("#message");

// HTML tags are displayed as text, not rendered
div.textContent = "<strong>Bold</strong>";
// Shows: <strong>Bold</strong>

Because any HTML in the string is treated as plain text, textContent is safe to use for displaying user input.

innerHTML

The innerHTML property gets or sets the HTML markup inside an element:

const container = document.querySelector("#container");

// Read HTML content
console.log(container.innerHTML); // "<p>Hello</p>"

// Set HTML content
container.innerHTML = "<p>New <strong>content</strong></p>";

Setting innerHTML parses the string as HTML and replaces all child nodes:

const list = document.querySelector("ul");
list.innerHTML = "<li>First</li><li>Second</li><li>Third</li>";

Attributes

There are several methods for reading and changing HTML attributes:

const link = document.querySelector("a");

// Get an attribute
const href = link.getAttribute("href");
console.log(href); // "https://example.com"

// Set an attribute
link.setAttribute("href", "https://newsite.com");
link.setAttribute("target", "_blank");

// Check if attribute exists
if (link.hasAttribute("target")) {
  console.log("Link opens in new tab");
}

// Remove an attribute
link.removeAttribute("target");

Common attributes are also available as direct properties:

const link = document.querySelector("a");
const input = document.querySelector("input");
const img = document.querySelector("img");

// Direct property access
console.log(link.href); // Full resolved URL
console.log(input.value); // Current input value
console.log(input.checked); // Checkbox state (boolean)
console.log(img.src); // Full resolved URL

// Set properties directly
input.value = "New value";
input.disabled = true;

The two are not the same thing. The attribute holds the initial value from the HTML, and the property holds the current value:

const input = document.querySelector("input");
// HTML: <input type="text" value="initial">

// User types "hello"
console.log(input.getAttribute("value")); // "initial" (HTML attribute)
console.log(input.value); // "hello" (current property)

Data Attributes

You can store your own data in data-* attributes and read it through the dataset property:

<div id="user" data-user-id="123" data-role="admin" data-active="true"></div>
const userDiv = document.querySelector("#user");

// Read data attributes (note: camelCase conversion)
console.log(userDiv.dataset.userId); // "123"
console.log(userDiv.dataset.role); // "admin"
console.log(userDiv.dataset.active); // "true" (string, not boolean)

// Set data attributes
userDiv.dataset.lastLogin = "2024-01-15";
// Creates: data-last-login="2024-01-15"

// Remove data attribute
delete userDiv.dataset.active;

Data attributes are always strings. Convert them when you need other types:

const id = Number(userDiv.dataset.userId);
const isActive = userDiv.dataset.active === "true";