Once you've selected DOM elements, the real magic begins—modifying them! JavaScript provides powerful properties and methods to change element content, styles, classes, and attributes dynamically. Whether you're updating text, applying styles, toggling classes, or working with attributes, mastering these modification techniques is essential for creating interactive web pages. Let's learn how to bring your pages to life!
textContent - Modifying Text Content
The textContent property sets or gets the text content of an element and its descendants. It treats everything as plain text.
Getting Text Content
<!DOCTYPE html>
<html>
<body>
<h1 id="title">Welcome to My Site</h1>
<p id="description">This is a <strong>great</strong> paragraph.</p>
<script>
let title = document.getElementById('title');
let description = document.getElementById('description');
// Get text content
console.log(title.textContent);
// "Welcome to My Site"
console.log(description.textContent);
// "This is a great paragraph."
// (HTML tags are stripped, only text is returned)
</script>
</body>
</html>Setting Text Content
<!DOCTYPE html>
<html>
<body>
<h1 id="title">Old Title</h1>
<p id="text">Old text</p>
<script>
let title = document.getElementById('title');
let text = document.getElementById('text');
// Set text content
title.textContent = 'New Title!';
text.textContent = 'This is the new text content.';
// HTML tags are escaped (treated as text)
text.textContent = '<strong>Bold text</strong>';
// Displays: <strong>Bold text</strong> (not bold!)
// Update with variable
let userName = 'Alice';
title.textContent = 'Welcome, ' + userName + '!';
// Or with template literal
title.textContent = `Welcome, ${userName}!`;
</script>
</body>
</html>Why use textContent?
- Safe—HTML tags are escaped (prevents XSS attacks)
- Faster than innerHTML for text-only content
- Simple and straightforward
- Perfect for displaying user input
innerHTML - Modifying HTML Content
The innerHTML property sets or gets the HTML markup inside an element. Unlike textContent, it parses and renders HTML tags.
Getting HTML Content
<!DOCTYPE html>
<html>
<body>
<div id="container">
<h2>Title</h2>
<p>Some <strong>bold</strong> text.</p>
</div>
<script>
let container = document.getElementById('container');
// Get HTML content
console.log(container.innerHTML);
// Output:
// <h2>Title</h2>
// <p>Some <strong>bold</strong> text.</p>
// innerHTML includes all HTML tags
</script>
</body>
</html>Setting HTML Content
<!DOCTYPE html>
<html>
<body>
<div id="container">Old content</div>
<script>
let container = document.getElementById('container');
// Set HTML content
container.innerHTML = '<h2>New Title</h2><p>New paragraph</p>';
// Add formatted text
container.innerHTML = '<p>This is <strong>bold</strong> and <em>italic</em>.</p>';
// Build complex HTML
let items = ['Apple', 'Banana', 'Orange'];
let html = '<ul>';
items.forEach(item => {
html += `<li>${item}</li>`;
});
html += '</ul>';
container.innerHTML = html;
// Or more elegantly
container.innerHTML = ``;
</script>
</body>
</html>textContent vs innerHTML
Choose based on your needs
textContent (Safe)
// textContent - plain text only
let element = document.getElementById('demo');
element.textContent = '<h1>Hello</h1>';
// Displays: <h1>Hello</h1>
// (literal text, not rendered as HTML)
// Safe for user input
let userInput = '<script>alert("XSS")</script>';
element.textContent = userInput;
// Displays the script as text (safe!)
// Gets only text, no HTML
console.log(element.textContent);
// Returns plain text onlyinnerHTML (Powerful but Risky)
// innerHTML - parses HTML
let element = document.getElementById('demo');
element.innerHTML = '<h1>Hello</h1>';
// Displays: Hello
// (rendered as actual HTML heading)
// DANGEROUS with user input!
let userInput = '<script>alert("XSS")</script>';
element.innerHTML = userInput;
// Executes the script! (XSS attack)
// Gets HTML markup
console.log(element.innerHTML);
// Returns HTML including tagsSecurity Warning: Never use innerHTML with user input or untrusted data! It can execute malicious scripts (XSS attacks). Use textContent for user input, or sanitize HTML before using innerHTML.
style Property - Inline Styles
The style property allows you to set inline CSS styles directly on elements.
Setting Styles
<!DOCTYPE html>
<html>
<body>
<div id="box">Box Content</div>
<button id="btn">Style Me</button>
<script>
let box = document.getElementById('box');
let btn = document.getElementById('btn');
// Set individual styles
box.style.color = 'blue';
box.style.backgroundColor = 'yellow';
box.style.fontSize = '20px';
box.style.padding = '20px';
box.style.border = '2px solid red';
box.style.borderRadius = '10px';
// Note: CSS properties with hyphens become camelCase
// background-color → backgroundColor
// font-size → fontSize
// border-radius → borderRadius
// Set multiple styles at once
btn.style.cssText = 'color: white; background-color: blue; padding: 10px;';
// Or use template literal
btn.style.cssText = `
color: white;
background-color: blue;
padding: 10px;
border: none;
border-radius: 5px;
cursor: pointer;
`;
</script>
</body>
</html>Getting Styles
let element = document.getElementById('box');
// Set a style
element.style.color = 'red';
// Get the style
console.log(element.style.color); // "red"
// But element.style only returns INLINE styles!
// It won't get styles from CSS files or <style> tags
// To get computed styles (all styles including CSS)
let computedStyle = window.getComputedStyle(element);
console.log(computedStyle.color); // Computed color
console.log(computedStyle.fontSize); // Computed font size
console.log(computedStyle.backgroundColor); // Computed background color
// Get specific computed style
let fontSize = window.getComputedStyle(element).fontSize;
console.log(fontSize); // e.g., "16px"Dynamic Styling
<!DOCTYPE html>
<html>
<body>
<div id="box" style="width: 100px; height: 100px; background: blue;"></div>
<button id="grow">Grow</button>
<button id="shrink">Shrink</button>
<button id="toggle">Toggle Color</button>
<script>
let box = document.getElementById('box');
let grow = document.getElementById('grow');
let shrink = document.getElementById('shrink');
let toggle = document.getElementById('toggle');
grow.addEventListener('click', function() {
let currentWidth = parseInt(box.style.width);
box.style.width = (currentWidth + 20) + 'px';
box.style.height = (currentWidth + 20) + 'px';
});
shrink.addEventListener('click', function() {
let currentWidth = parseInt(box.style.width);
if (currentWidth > 20) {
box.style.width = (currentWidth - 20) + 'px';
box.style.height = (currentWidth - 20) + 'px';
}
});
toggle.addEventListener('click', function() {
if (box.style.backgroundColor === 'blue') {
box.style.backgroundColor = 'red';
} else {
box.style.backgroundColor = 'blue';
}
});
</script>
</body>
</html>CSS Property Name Conversions:
background-color→backgroundColorfont-size→fontSizeborder-radius→borderRadiusmargin-top→marginToptext-align→textAlign
classList - Managing CSS Classes
The classList property provides methods to add, remove, toggle, and check for CSS classes. This is the modern, preferred way to work with classes.
classList Methods
<!DOCTYPE html>
<html>
<head>
<style>
.highlight { background-color: yellow; }
.bold { font-weight: bold; }
.large { font-size: 24px; }
.hidden { display: none; }
</style>
</head>
<body>
<p id="text">Sample text</p>
<script>
let text = document.getElementById('text');
// Add a class
text.classList.add('highlight');
// <p id="text" class="highlight">Sample text</p>
// Add multiple classes
text.classList.add('bold', 'large');
// <p id="text" class="highlight bold large">Sample text</p>
// Remove a class
text.classList.remove('bold');
// <p id="text" class="highlight large">Sample text</p>
// Toggle a class (add if not present, remove if present)
text.classList.toggle('hidden');
// Toggles visibility
// Check if class exists
if (text.classList.contains('highlight')) {
console.log('Element is highlighted');
}
// Replace a class
text.classList.replace('large', 'small');
// Replaces 'large' with 'small'
</script>
</body>
</html>Practical Class Manipulation
<!DOCTYPE html>
<html>
<head>
<style>
.tab { padding: 10px; cursor: pointer; background: #eee; }
.tab.active { background: blue; color: white; }
.content { display: none; padding: 20px; }
.content.active { display: block; }
</style>
</head>
<body>
<div class="tab" data-tab="1">Tab 1</div>
<div class="tab" data-tab="2">Tab 2</div>
<div class="tab" data-tab="3">Tab 3</div>
<div class="content active" data-content="1">Content 1</div>
<div class="content" data-content="2">Content 2</div>
<div class="content" data-content="3">Content 3</div>
<script>
let tabs = document.querySelectorAll('.tab');
let contents = document.querySelectorAll('.content');
tabs.forEach(tab => {
tab.addEventListener('click', function() {
let tabNum = this.getAttribute('data-tab');
// Remove active from all tabs
tabs.forEach(t => t.classList.remove('active'));
// Add active to clicked tab
this.classList.add('active');
// Remove active from all content
contents.forEach(c => c.classList.remove('active'));
// Add active to corresponding content
let targetContent = document.querySelector(`[data-content="${tabNum}"]`);
targetContent.classList.add('active');
});
});
</script>
</body>
</html>classList vs className
classList is much cleaner
className (Old Way)
// Old way: className
let element = document.getElementById('box');
// Set classes (replaces ALL classes)
element.className = 'box highlight';
// Add a class (awkward)
element.className += ' active';
// Remove a class (very awkward)
element.className = element.className
.replace('highlight', '')
.trim();
// Check if class exists (manual)
if (element.className.indexOf('active') !== -1) {
console.log('Has active class');
}classList (Modern Way)
// Modern way: classList
let element = document.getElementById('box');
// Add class (doesn't affect others)
element.classList.add('highlight');
// Add multiple
element.classList.add('box', 'active');
// Remove class (clean)
element.classList.remove('highlight');
// Toggle class
element.classList.toggle('active');
// Check if class exists (clean)
if (element.classList.contains('active')) {
console.log('Has active class');
}Working with Attributes
Elements have attributes like id, src, href, data-*, etc. JavaScript provides methods to get, set, and remove attributes.
Attribute Methods
<!DOCTYPE html>
<html>
<body>
<img id="logo" src="old-logo.png" alt="Logo">
<a id="link" href="https://example.com">Link</a>
<input id="username" type="text" placeholder="Username">
<script>
let logo = document.getElementById('logo');
let link = document.getElementById('link');
let input = document.getElementById('username');
// Get attribute
console.log(logo.getAttribute('src')); // "old-logo.png"
console.log(link.getAttribute('href')); // "https://example.com"
// Set attribute
logo.setAttribute('src', 'new-logo.png');
logo.setAttribute('alt', 'New Logo');
link.setAttribute('href', 'https://newsite.com');
link.setAttribute('target', '_blank');
// Check if attribute exists
if (logo.hasAttribute('alt')) {
console.log('Logo has alt text');
}
// Remove attribute
input.removeAttribute('placeholder');
// List all attributes
console.log(logo.attributes);
// Returns NamedNodeMap of all attributes
</script>
</body>
</html>Data Attributes
<!DOCTYPE html>
<html>
<body>
<button id="btn" data-user-id="123" data-role="admin" data-active="true">
Click Me
</button>
<script>
let btn = document.getElementById('btn');
// Access data attributes with dataset
console.log(btn.dataset.userId); // "123"
console.log(btn.dataset.role); // "admin"
console.log(btn.dataset.active); // "true"
// Note: data-user-id becomes dataset.userId (camelCase)
// Set data attribute
btn.dataset.status = 'online';
// Creates data-status="online"
btn.dataset.lastLogin = '2024-01-15';
// Creates data-last-login="2024-01-15"
// Or use setAttribute
btn.setAttribute('data-count', '5');
console.log(btn.dataset.count); // "5"
// Practical use: store data on elements
let products = document.querySelectorAll('.product');
products.forEach(product => {
product.addEventListener('click', function() {
let productId = this.dataset.productId;
let price = this.dataset.price;
console.log(`Product ${productId} costs $${price}`);
});
});
</script>
</body>
</html>Direct Property Access
let img = document.getElementById('logo');
let link = document.getElementById('link');
let input = document.getElementById('username');
// Many attributes can be accessed directly as properties
console.log(img.src); // Get src
img.src = 'new.png'; // Set src
console.log(link.href); // Get href
link.href = 'https://new.com'; // Set href
console.log(input.value); // Get value
input.value = 'New value'; // Set value
console.log(input.type); // "text"
input.type = 'password'; // Change to password input
// Direct property vs getAttribute
console.log(link.href); // Full URL: "https://example.com/page"
console.log(link.getAttribute('href')); // Exactly as written: "/page"
// Some properties are read-only
console.log(input.type); // Can read
// input.type is read-only for some input typesPractical Examples
Example 1: Interactive Theme Switcher
<!DOCTYPE html>
<html>
<head>
<style>
body { transition: all 0.3s; }
body.dark-theme {
background-color: #1a1a1a;
color: #ffffff;
}
body.light-theme {
background-color: #ffffff;
color: #000000;
}
.theme-btn {
padding: 10px 20px;
margin: 10px;
cursor: pointer;
}
</style>
</head>
<body class="light-theme">
<h1 id="title">Theme Switcher</h1>
<p id="description">Click buttons to change theme</p>
<button class="theme-btn" data-theme="light">Light</button>
<button class="theme-btn" data-theme="dark">Dark</button>
<button id="toggle">Toggle Theme</button>
<script>
let body = document.body;
let buttons = document.querySelectorAll('.theme-btn');
let toggle = document.getElementById('toggle');
// Set theme from buttons
buttons.forEach(btn => {
btn.addEventListener('click', function() {
let theme = this.dataset.theme;
body.className = theme + '-theme';
localStorage.setItem('theme', theme);
});
});
// Toggle theme
toggle.addEventListener('click', function() {
if (body.classList.contains('light-theme')) {
body.classList.replace('light-theme', 'dark-theme');
} else {
body.classList.replace('dark-theme', 'light-theme');
}
});
// Load saved theme
let savedTheme = localStorage.getItem('theme');
if (savedTheme) {
body.className = savedTheme + '-theme';
}
</script>
</body>
</html>Example 2: Dynamic Content Generator
<!DOCTYPE html>
<html>
<body>
<div id="controls">
<input type="text" id="title" placeholder="Title">
<textarea id="content" placeholder="Content"></textarea>
<button id="generate">Generate Card</button>
</div>
<div id="output"></div>
<script>
let titleInput = document.getElementById('title');
let contentInput = document.getElementById('content');
let generateBtn = document.getElementById('generate');
let output = document.getElementById('output');
generateBtn.addEventListener('click', function() {
let title = titleInput.value;
let content = contentInput.value;
if (!title || !content) {
alert('Please fill in all fields');
return;
}
// Create card HTML
let cardHTML = `
<div class="card" style="
border: 1px solid #ddd;
padding: 20px;
margin: 10px 0;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
">
<h2 style="margin: 0 0 10px 0; color: #333;">${title}</h2>
<p style="margin: 0; color: #666;">${content}</p>
<button onclick="this.parentElement.remove()" style="
margin-top: 10px;
padding: 5px 10px;
background: red;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
">Delete</button>
</div>
`;
// Add card to output
output.innerHTML += cardHTML;
// Clear inputs
titleInput.value = '';
contentInput.value = '';
});
</script>
</body>
</html>Element Modification Practice
Master textContent, innerHTML, style, and classList
console.log() to see your output in the console above.Key Takeaways
textContentsets/gets plain text (safe, fast)innerHTMLsets/gets HTML markup (powerful but risky)- Use textContent for user input to prevent XSS attacks
element.style.propertysets inline CSS styles- CSS property names become camelCase (background-color → backgroundColor)
classListis the modern way to manage CSS classes- Use
classList.add(),remove(),toggle(),contains() - Prefer CSS classes over inline styles for maintainability
- Use
getAttribute()andsetAttribute()for attributes - Data attributes are accessed via
datasetproperty
What's Next?
You now know how to modify DOM elements—changing content with textContent and innerHTML, applying styles with the style property, managing classes with classList, and working with attributes! These are the core skills for creating dynamic, interactive web pages.
In the next lesson, we'll explore Creating and Removing Elements—learning how to dynamically create new HTML elements, append them to the page, and remove existing ones. This enables you to build truly dynamic interfaces!
💪 Practice Challenge:
Before moving on, try creating:
- A button that changes a heading's text when clicked
- A style switcher that changes multiple CSS properties
- A toggle button that adds/removes a CSS class
- A form that displays user input safely using textContent
- A theme switcher that saves preference in localStorage