Skip to Content
Course content

79: Manipulating Content and Attributes

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've spent a lot of time reviewing junior code, and there is one pattern that pops up almost every single time we get to DOM manipulation: the reflexive use of innerHTML for every single text change. It feels like the "Swiss Army Knife" of the DOM, and because it works, many developers assume it's the best tool for the job.

"innerHTML is the universal tool" vs "textContent is your safety net"

Let's look at why relying solely on innerHTML is a mistake. Imagine you're building a simple comment section. You have a variable userName that comes from a database or a user input field, and you want to put it inside a span.

const userName = "<img src='x' onerror='alert(\"Hacked!\")'>";
const display = document.querySelector('#user-display');

// The "common" way
display.innerHTML = userName; 

If you use innerHTML here, the browser doesn't just see a string; it sees HTML instructions. In this case, it executes a malicious script. This is a classic Cross-Site Scripting (XSS) vulnerability. Even if you aren't worried about hackers, innerHTML is expensive. It forces the browser to tear down the existing DOM nodes inside that element and rebuild them from scratch, which kills performance if you're doing it inside a loop.

The fix is textContent. It tells the browser: "Treat this strictly as raw text. Do not parse it. Do not execute it."

// The professional way
display.textContent = userName; 
// Result: The actual string "<img src..." is printed literally on the screen. No alert.

I only use innerHTML when I actually intend to inject HTML tags (like adding a tag inside a paragraph). For everything else, textContent is the gold standard.

"Attributes are only changed via setAttribute" vs "Direct property access is cleaner"

When you start manipulating attributes—like changing an image source or disabling a button—you'll see setAttribute('attribute', 'value') used everywhere. It's not wrong, but it's often unnecessary and verbose.

Most standard HTML attributes are mirrored as properties on the DOM object. For example, instead of this:

const profilePic = document.querySelector('#avatar');
profilePic.setAttribute('src', 'assets/new-photo.jpg');
profilePic.setAttribute('alt', 'New Profile Picture');

You can just do this:

const profilePic = document.querySelector('#avatar');
profilePic.src = 'assets/new-photo.jpg';
profilePic.alt = 'New Profile Picture';

It's shorter, reads more like standard JavaScript, and is generally faster. Now, you still need setAttribute for custom data attributes (like data-user-id), because those don't have direct properties on the element object. But for the common stuff—id, src, value, disabled—just hit the property directly.




📋 Practical Task

Build a Dynamic User Profile Toggle

You are building a profile card that needs to be updated dynamically based on a user's status. Create a small HTML snippet with an image (<img id="user-avatar">), a name (<span id="user-name">), and a "Status" button (<button id="status-btn">).

Write a JavaScript function that does the following when the button is clicked:

  1. Changes the user-name to "Jane Doe" using textContent.
  2. Updates the user-avatar source to "https://i.pravatar.cc/150?u=jane" using direct property access.
  3. Sets a custom data attribute data-status="active" on the button using setAttribute.
  4. Changes the button's own text to "Profile Updated" and sets its disabled property to true.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.