Creating and Modifying Elements in JavaScript DOM

Learn how to create new DOM elements, add or remove them dynamically, modify element attributes, and manage CSS classes using classList to build interactive and maintainable web interfaces.

Introduction to DOM Manipulation

The Document Object Model (DOM) is a programming interface for web documents that represents the page as a tree of objects. DOM manipulation is one of the most essential skills in JavaScript development, allowing you to create dynamic, interactive web applications by programmatically creating, modifying, and removing HTML elements.

Creating New Elements

The createElement() Method

The document.createElement() method is the primary way to create new HTML elements dynamically in JavaScript. This method creates an element node in memory, which you can then customize before adding it to the page.

javascript
const element = document.createElement(tagName);
Practical Examples:
javascript
// Create a div element
const newDiv = document.createElement('div');

// Create a paragraph
const paragraph = document.createElement('p');

// Create a button
const button = document.createElement('button');

// Create an image
const image = document.createElement('img');

// Create a list item
const listItem = document.createElement('li');

Adding Content to New Elements

Once you've created an element, you'll typically want to add content to it. There are several ways to do this:

Using textContent:

javascript
const heading = document.createElement('h2');
heading.textContent = 'Welcome to My Website';

Using innerHTML (for HTML content):

javascript
const div = document.createElement('div');
div.innerHTML = '<strong>Bold text</strong> and normal text';
Creating text nodes:
javascript
const paragraph = document.createElement('p');
const textNode = document.createTextNode('This is a text node');
paragraph.appendChild(textNode);
Best Practice: Use textContent for plain text (safer and faster) and innerHTML only when you need to include HTML markup.

Adding and Removing Elements

Adding Elements to the DOM

After creating an element, you need to insert it into the document to make it visible. JavaScript provides several methods for this purpose.

appendChild()

javascript
const container = document.getElementById('container');
const newParagraph = document.createElement('p');
newParagraph.textContent = 'This is a new paragraph';

container.appendChild(newParagraph);

append()

The append() method is more flexible than appendChild() and can accept multiple nodes or strings.
javascript
const div = document.getElementById('myDiv');

// Can append multiple elements at once
div.append('Some text', document.createElement('br'), 'More text');

// Can append multiple elements
const p1 = document.createElement('p');
const p2 = document.createElement('p');
div.append(p1, p2);

insertBefore()

Insert a new element before an existing element

javascript
const parent = document.getElementById('parent');
const newElement = document.createElement('div');
const referenceElement = document.getElementById('reference');

parent.insertBefore(newElement, referenceElement);

insertAdjacentElement()

This method provides precise control over where to insert an element.

javascript
const targetElement = document.getElementById('target');
const newElement = document.createElement('div');

// Positions: 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
targetElement.insertAdjacentElement('beforebegin', newElement);
Position values explained:
  • beforebegin: Inserts content before the element itself
  • afterbegin: Inserts content inside the element, before its first child
  • beforeend: Inserts content inside the element, after its last child
  • afterend: Inserts content after the element itself

Removing Elements from the DOM

remove()

The modern and simplest way to remove an element.

javascript
const element = document.getElementById('myElement');
element.remove();

removeChild()

The traditional method that requires access to the parent element.

javascript
const parent = document.getElementById('parent');
const child = document.getElementById('child');

parent.removeChild(child);

Replacing Elements

javascript
const parent = document.getElementById('parent');
const oldElement = document.getElementById('old');
const newElement = document.createElement('div');

parent.replaceChild(newElement, oldElement);

// Or using the newer replaceWith() method
oldElement.replaceWith(newElement);

Modifying Attributes

Attributes provide additional information about HTML elements. JavaScript offers multiple ways to read, set, and remove attributes dynamically.

getAttribute() and setAttribute()

These methods work with any HTML attribute.

javascript
const link = document.getElementById('myLink');

// Get an attribute value
const href = link.getAttribute('href');
console.log(href); // Output: the URL

// Set an attribute
link.setAttribute('href', 'https://example.com');
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noopener noreferrer');

Direct Property Access

<p>Many common attributes can be accessed as properties directly. </p>
javascript
const image = document.getElementById('myImage');

// Setting attributes via properties
image.src = 'photo.jpg';
image.alt = 'A beautiful landscape';
image.width = 300;
image.height = 200;

const input = document.getElementById('username');
input.value = 'JohnDoe';
input.placeholder = 'Enter your username';
input.disabled = false;

hasAttribute() and removeAttribute()

Check for the existence of attributes and remove them when needed.

javascript
const button = document.getElementById('submitBtn');

// Check if attribute exists
if (button.hasAttribute('disabled')) {
    console.log('Button is disabled');
}

// Remove an attribute
button.removeAttribute('disabled');

// Check for data attributes
if (button.hasAttribute('data-user-id')) {
    const userId = button.getAttribute('data-user-id');
}

Working with Data Attributes

Data attributes (data-*) provide a way to store custom data in HTML elements

javascript
const element = document.getElementById('product');

// Setting data attributes
element.setAttribute('data-product-id', '12345');
element.setAttribute('data-price', '29.99');
element.setAttribute('data-category', 'electronics');

// Reading data attributes (two methods)
const productId = element.getAttribute('data-product-id');
// or using the dataset property
const price = element.dataset.price;
const category = element.dataset.category;

// Setting via dataset
element.dataset.inStock = 'true';

ClassList Manipulation

The classList property provides a powerful and convenient way to manage CSS classes on elements. It's more efficient and cleaner than manipulating the className property directly.

classList.add()

Add one or more classes to an element.

javascript
const element = document.getElementById('myElement');

// Add a single class
element.classList.add('active');

// Add multiple classes
element.classList.add('highlight', 'animated', 'fade-in');

classList.remove()

<p.Remove one or more classes from an element.</p>
javascript
const element = document.getElementById('myElement');

// Remove a single class
element.classList.remove('active');

// Remove multiple classes
element.classList.remove('highlight', 'animated');

classList.toggle()

Toggle a class on or off. This is extremely useful for interactive elements.

javascript
const button = document.getElementById('menuButton');
const menu = document.getElementById('menu');

button.addEventListener('click', () => {
    // Toggles the 'open' class
    menu.classList.toggle('open');
});

// Toggle with a condition (second parameter)
const isVisible = true;
menu.classList.toggle('hidden', !isVisible); // Adds 'hidden' if isVisible is false

classList.contains()

Check if an element has a specific class.

javascript
const element = document.getElementById('myElement');

if (element.classList.contains('active')) {
    console.log('Element is active');
} else {
    console.log('Element is not active');
}

classList.replace()

Replace an existing class with a new one.

javascript
const element = document.getElementById('myElement');

// Replace 'old-class' with 'new-class'
element.classList.replace('old-class', 'new-class');

Practical ClassList Examples

Example 1: Tab Navigation
javascript
const tabs = document.querySelectorAll('.tab');
const contents = document.querySelectorAll('.tab-content');

tabs.forEach((tab, index) => {
    tab.addEventListener('click', () => {
        // Remove active class from all tabs
        tabs.forEach(t => t.classList.remove('active'));
        contents.forEach(c => c.classList.remove('active'));
        
        // Add active class to clicked tab
        tab.classList.add('active');
        contents[index].classList.add('active');
    });
});
Example 2: Accordion Menu
javascript
const accordionHeaders = document.querySelectorAll('.accordion-header');

accordionHeaders.forEach(header => {
    header.addEventListener('click', () => {
        const content = header.nextElementSibling;
        
        // Toggle open class
        header.classList.toggle('open');
        content.classList.toggle('expanded');
    });
});
Example 3: Form Validation Visual Feedback
javascript
const emailInput = document.getElementById('email');

emailInput.addEventListener('blur', () => {
    const isValid = emailInput.value.includes('@');
    
    if (isValid) {
        emailInput.classList.remove('error');
        emailInput.classList.add('success');
    } else {
        emailInput.classList.remove('success');
        emailInput.classList.add('error');
    }
});
Example 4: Loading State Management
javascript
const button = document.getElementById('submitBtn');

async function submitForm() {
    // Add loading state
    button.classList.add('loading', 'disabled');
    button.textContent = 'Loading...';
    
    try {
        await fetch('/api/submit', { method: 'POST' });
        button.classList.remove('loading', 'disabled');
        button.classList.add('success');
        button.textContent = 'Success!';
    } catch (error) {
        button.classList.remove('loading');
        button.classList.add('error');
        button.textContent = 'Error!';
    }
}

Best Practices and Performance Tips

1. Minimize DOM Manipulations

DOM operations are expensive. Batch your changes when possible.

javascript
// ❌ Bad: Multiple reflows
for (let i = 0; i < 100; i++) {
    const li = document.createElement('li');
    li.textContent = `Item ${i}`;
    list.appendChild(li);
}

// ✅ Good: Single reflow
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
    const li = document.createElement('li');
    li.textContent = `Item ${i}`;
    fragment.appendChild(li);
}
list.appendChild(fragment);

2. Cache DOM References

Don't query the DOM repeatedly for the same element.

javascript
// ❌ Bad
document.getElementById('myElement').classList.add('class1');
document.getElementById('myElement').classList.add('class2');
document.getElementById('myElement').classList.add('class3');

// ✅ Good
const element = document.getElementById('myElement');
element.classList.add('class1', 'class2', 'class3');

3. Use classList Instead of className

The classList API is more maintainable and less error-prone.

javascript
// ❌ Avoid
element.className = element.className + ' new-class';

// ✅ Better
element.classList.add('new-class');

4. Event Delegation

Instead of adding listeners to many elements, use delegation.

javascript
// ✅ Good: One listener on parent
document.getElementById('list').addEventListener('click', (e) => {
    if (e.target.tagName === 'LI') {
        e.target.classList.toggle('selected');
    }
});

Frequently Asked Questions

DOM manipulation refers to the process of using JavaScript to dynamically create, modify, or delete HTML elements and their attributes on a web page. It allows developers to make websites interactive by responding to user actions, updating content without page reloads, and creating dynamic user interfaces.

createElement() creates a new DOM element node that you can customize and append to the document, offering better performance and security. innerHTML sets or gets HTML content as a string, which is convenient for adding multiple elements at once but can be slower and poses security risks if used with user-generated content. For creating single elements with attributes and event listeners, use createElement(). For inserting simple HTML structures, innerHTML is acceptable.

textContent gets or sets the text content of an element including hidden elements and is faster because it doesn't trigger reflow. innerText is aware of CSS styling and only returns visible text, making it slower. Best practice: use textContent for better performance unless you specifically need to respect CSS visibility.

Use the classList.contains() method to check if an element has a specific class. For example: element.classList.contains('active') returns true if the element has the class "active" and false otherwise. This is more reliable than checking the className property directly.

Yes, the classList.add() method accepts multiple class names as separate arguments