Understanding CSS Classes and DOM Manipulation
CSS classes are reusable style definitions that can be applied to multiple HTML elements. Unlike IDs, which must be unique on a page, classes can be shared across any number of elements. This makes them the primary mechanism for applying consistent styling and behavior throughout a website.
When working with class manipulation in JavaScript, it's important to understand that the class attribute is part of the element's DOM representation. Modern browsers provide the classList property, which returns a DOMTokenList object containing the element's classes.
The DOMTokenList Interface
The DOMTokenList interface represents a set of space-separated tokens. When you access an element's classList property, you receive a live DOMTokenList that automatically updates to reflect the current state of the element's class attribute. This live nature means that any changes made through the classList methods are immediately reflected in the collection.
Class manipulation is central to building interactive user interfaces in modern web development. Toggle menus, accordions, modals, tabs, and form validation all rely on adding or removing classes to trigger CSS-based behaviors and visual changes. For foundational CSS knowledge, explore our guide on CSS background images and responsive images techniques to understand how classes control visual presentation.
1// Add a single class2element.classList.add('active');3 4// Add multiple classes at once5element.classList.add('featured', 'highlighted', 'premium');Vanilla JavaScript: The Modern classList.add() Method
The classList.add() method is the modern, recommended way to add CSS classes to HTML elements in vanilla JavaScript. The method accepts one or more class names as arguments and adds them to the element's class attribute.
Unlike older approaches that required parsing and string manipulation, the classList methods handle edge cases like duplicate classes automatically and provide a clean, chainable API.
Adding a Single Class
const button = document.querySelector('#submit-btn');
button.classList.add('active');
// <button id="submit-btn" class="active">Submit</button>
Adding Multiple Classes at Once
One of the advantages of classList.add() is the ability to add multiple classes in a single call, which is more efficient than multiple separate calls. This approach reduces function call overhead and keeps your code concise.
Adding Classes to Multiple Elements
For situations where you need to add classes to multiple elements, combine classList.add() with querySelectorAll():
const listItems = document.querySelectorAll('.navigation li');
listItems.forEach(item => {
item.classList.add('nav-item');
});
Working with Dynamic Class Names
Class names can be constructed dynamically based on application state:
function handleStatusChange(status) {
const statusIndicator = document.getElementById('status');
statusIndicator.classList.remove('success', 'warning', 'error');
statusIndicator.classList.add(status);
}
Understanding the trade-offs between approaches
Browser Support
jQuery addClass supports IE9+, while classList.add() works in IE10+ with full support in IE11+
Bundle Size
Vanilla JavaScript requires ~0KB (native API), while jQuery adds ~30KB to your bundle
Performance
Vanilla JavaScript is faster due to native implementation without jQuery overhead
Multiple Classes
Both approaches support adding multiple classes in a single call
jQuery addClass() Method: The Legacy Approach
For many years, jQuery dominated frontend development, and its addClass() method became synonymous with dynamic class manipulation. While modern vanilla JavaScript has largely replaced this need, jQuery remains prevalent in legacy applications.
If you're working with older codebases that rely on jQuery, consider migrating to modern frameworks. Our guide on moving from jQuery to Vue provides a comprehensive roadmap for modernization. Additionally, our article on jQuery vertical tabs and sliding content demonstrates common patterns that can be implemented with vanilla JavaScript.
Syntax and Parameters
// Single class name
$('#myElement').addClass('active');
// Multiple class names
$('.card').addClass('featured highlight');
// Function that returns class names
$('li').addClass(function(index, currentClass) {
return 'item-' + index;
});
Callback Functions for Dynamic Class Assignment
One powerful feature of jQuery's addClass() is the ability to use a function to determine which classes to add based on the element's index or other properties. This allows for dynamic, programmatic class assignment based on element state or data attributes.
Alternative Methods for Adding Classes
Using the className Property
The className property provides a direct way to manipulate the class attribute as a string:
const element = document.getElementById('myElement');
// Append a class without removing existing ones
element.className += ' additional-class';
// Or with proper spacing
element.className = element.className.trim() + ' additional-class';
Using setAttribute() Method
const element = document.querySelector('.target');
element.setAttribute('class', 'new-class');
Note: These methods completely replace existing classes and require manual handling of spacing and duplicates. For most use cases, the classList API is the preferred approach.
Removing and Toggling Classes
The classList API provides complementary methods:
- remove() - Removes specified classes from an element
- toggle() - Adds a class if it doesn't exist, removes it if it does
- contains() - Checks if a specific class exists
Best Practices for Class Manipulation
Performance Considerations
- Batch Operations: Use a single call to classList.add() with multiple arguments rather than multiple separate calls
- Avoid Layout Thrashing: Read layout properties after class changes to minimize reflows
- Use Native APIs: Prefer classList over className or setAttribute for cleaner, more efficient code
Semantic Class Naming
Use meaningful, semantic class names that describe the state or purpose:
// Good: Describes the state
element.classList.add('is-loading');
element.classList.add('has-error');
element.classList.add('is-interactive');
Writing clean, well-documented code goes hand-in-hand with proper class manipulation. See our guide on the art of comments for best practices in documenting your JavaScript code.
Accessibility Considerations
When adding classes that affect visibility or interactivity, ensure proper accessibility:
element.classList.add('visually-hidden');
element.setAttribute('aria-hidden', 'true');
element.classList.add('modal-open');
element.setAttribute('aria-modal', 'true');
For complex applications, abstract class manipulation into reusable utility functions to maintain consistency and reduce duplication across your codebase.
1// Interactive Button States2class ButtonHandler {3 constructor(button) {4 this.button = button;5 }6 7 setLoading(loading) {8 this.button.classList.toggle('loading', loading);9 this.button.classList.toggle('disabled', loading);10 this.button.disabled = loading;11 }12}13 14// Accordion Component15function toggleAccordion(header) {16 const content = header.nextElementSibling;17 header.classList.toggle('expanded');18 content.classList.toggle('expanded');19}20 21// Dynamic Form Validation22function validateField(field, isValid) {23 field.classList.toggle('valid', isValid);24 field.classList.toggle('invalid', !isValid);25}