How can I change an element’s class with JavaScript?
How can I change the class of an HTML element in response to an onclick or any other events using JavaScript?
You can change an element’s class using JavaScript by accessing the element’s className property or using the classList API. The most modern approach is to use classList.add(), classList.remove(), and classList.toggle() methods to manipulate classes in response to events like onclick.
Contents
- Basic Methods for Changing Classes
- Event Handling for Class Changes
- Practical Examples
- Advanced Techniques
- Best Practices and Browser Compatibility
Basic Methods for Changing Classes
JavaScript provides several ways to modify an element’s class attribute, each with different use cases and levels of functionality.
className Property
The className property allows you to get or set the class attribute of an element as a single string:
// Get current classes
const currentClasses = element.className;
// Set entire class string
element.className = 'new-class another-class';
// Add to existing classes
element.className += ' additional-class';
classList API
The modern classList API provides more granular control over class manipulation:
// Add a class
element.classList.add('new-class');
// Remove a class
element.classList.remove('old-class');
// Toggle a class (add if exists, remove if doesn't)
element.classList.toggle('active-class');
// Check if element has a class
if (element.classList.contains('specific-class')) {
// Element has the class
}
// Replace a class
element.classList.replace('old-class', 'new-class');
The
classListAPI is more powerful thanclassNamebecause it allows individual class manipulation without affecting other classes on the element.
Direct Attribute Manipulation
You can also work with the class attribute directly:
// Using setAttribute
element.setAttribute('class', 'new-class');
// Using getAttribute
const classes = element.getAttribute('class');
Event Handling for Class Changes
To change classes in response to events, you need to set up event listeners or use inline event handlers.
Event Listeners
Modern JavaScript prefers event listeners for better control and multiple handler support:
// Get the element
const button = document.getElementById('myButton');
const box = document.getElementById('myBox');
// Add click event listener
button.addEventListener('click', function() {
box.classList.toggle('active');
});
// Multiple event types
element.addEventListener('mouseenter', function() {
this.classList.add('hovered');
});
element.addEventListener('mouseleave', function() {
this.classList.remove('hovered');
});
Inline Event Handlers
For simple cases, you can use inline handlers in HTML:
<button onclick="document.getElementById('box').classList.toggle('active')">
Toggle Class
</button>
<button onclick="this.classList.add('clicked')">
Add Class to This Button
</button>
Event Delegation
For dynamic content or better performance, use event delegation:
// Handle clicks on any element with class 'toggle-button'
document.addEventListener('click', function(event) {
if (event.target.classList.contains('toggle-button')) {
const targetId = event.target.dataset.target;
const targetElement = document.getElementById(targetId);
if (targetElement) {
targetElement.classList.toggle('active');
}
}
});
Practical Examples
Tab Interface Example
Create a functional tab system where clicking tabs changes content visibility:
<div class="tabs">
<button class="tab-button active" data-tab="tab1">Tab 1</button>
<button class="tab-button" data-tab="tab2">Tab 2</button>
<button class="tab-button" data-tab="tab3">Tab 3</button>
</div>
<div class="tab-content">
<div id="tab1" class="tab-pane active">Content for Tab 1</div>
<div id="tab2" class="tab-pane">Content for Tab 2</div>
<div id="tab3" class="tab-pane">Content for Tab 3</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const tabButtons = document.querySelectorAll('.tab-button');
tabButtons.forEach(button => {
button.addEventListener('click', function() {
// Remove active class from all buttons and panes
tabButtons.forEach(btn => btn.classList.remove('active'));
document.querySelectorAll('.tab-pane').forEach(pane => {
pane.classList.remove('active');
});
// Add active class to clicked button and corresponding pane
this.classList.add('active');
const tabId = this.dataset.tab;
document.getElementById(tabId).classList.add('active');
});
});
});
</script>
Theme Toggle Example
Create a light/dark mode toggle:
<button id="themeToggle">Toggle Theme</button>
<script>
const themeToggle = document.getElementById('themeToggle');
const body = document.body;
// Check for saved theme preference or default to light
const currentTheme = localStorage.getItem('theme') || 'light';
body.className = currentTheme;
themeToggle.addEventListener('click', function() {
const newTheme = body.classList.contains('dark') ? 'light' : 'dark';
body.className = newTheme;
localStorage.setItem('theme', newTheme);
});
</script>
Interactive Card Example
Create cards that expand when clicked:
<div class="card" onclick="this.classList.toggle('expanded')">
<div class="card-header">Card Title</div>
<div class="card-content">
Click this card to expand it and see more content.
</div>
<div class="card-details" style="display: none;">
This additional content appears when the card is expanded.
</div>
</div>
<style>
.card.expanded .card-details {
display: block;
}
</style>
Advanced Techniques
Conditional Class Changes
Add classes based on conditions:
// Add class based on element content length
const textElement = document.getElementById('long-text');
if (textElement.textContent.length > 100) {
textElement.classList.add('long-text');
}
// Add class based on screen size
function updateResponsiveClass() {
const container = document.getElementById('responsive-container');
if (window.innerWidth < 768) {
container.classList.add('mobile-layout');
} else {
container.classList.remove('mobile-layout');
}
}
// Call on load and resize
updateResponsiveClass();
window.addEventListener('resize', updateResponsiveClass);
Animation Classes
Use classes to trigger CSS animations:
function animateElement(element) {
element.classList.add('animate-fade-in');
// Remove animation class after animation completes
setTimeout(() => {
element.classList.remove('animate-fade-in');
}, 1000); // Match CSS animation duration
}
// Usage
const button = document.getElementById('animateButton');
button.addEventListener('click', function() {
const target = document.getElementById('animatedBox');
animateElement(target);
});
Class Management Utilities
Create utility functions for complex class management:
const ClassManager = {
add: function(element, className) {
if (!element.classList.contains(className)) {
element.classList.add(className);
}
},
remove: function(element, className) {
element.classList.remove(className);
},
toggle: function(element, className) {
element.classList.toggle(className);
},
replace: function(element, oldClass, newClass) {
if (element.classList.contains(oldClass)) {
element.classList.replace(oldClass, newClass);
}
},
has: function(element, className) {
return element.classList.contains(className);
}
};
// Usage
ClassManager.add(myElement, 'highlight');
ClassManager.toggle(myElement, 'visible');
Best Practices and Browser Compatibility
Modern Browser Support
The classList API is supported in all modern browsers:
- Chrome 8+
- Firefox 3.6+
- Safari 5.1+
- Edge 12+
- Opera 11.5+
Polyfills for Older Browsers
For Internet Explorer 9 and below, include a polyfill:
// classList polyfill for IE9
if (!('classList' in document.createElement('div'))) {
(function (view) {
'use strict';
if (!('Element' in view)) return;
var ElementPrototype = Element.prototype;
if (!Object.defineProperty) return;
if (Object.defineProperty(ElementPrototype, 'classList', { get: function() {
var self = this;
function update(fn) {
return function(value) {
var classes = self.className.baseVal || self.className;
var tokens = classes ? classes.split(/\s+/) : [];
fn(tokens, value);
self.className = tokens.join(' ');
};
}
var ret = {
add: update(function(tokens, value) {
if (tokens.indexOf(value) === -1) {
tokens.push(value);
}
}),
remove: update(function(tokens, value) {
var index = tokens.indexOf(value);
if (index !== -1) {
tokens.splice(index, 1);
}
}),
toggle: update(function(tokens, value) {
var index = tokens.indexOf(value);
if (index === -1) {
tokens.push(value);
} else {
tokens.splice(index, 1);
}
}),
contains: function(value) {
var classes = self.className.baseVal || self.className;
return (classes ? classes.split(/\s+/) : []).indexOf(value) !== -1;
},
item: function(i) {
var classes = self.className.baseVal || self.className;
return (classes ? classes.split(/\s+/) : [])[i];
}
};
Object.defineProperty(ret, 'length', {
get: function() {
var classes = self.className.baseVal || self.className;
return (classes ? classes.split(/\s+/) : []).length;
}
});
return ret;
}})) {
throw new Error('Could not add classList property to Element prototype');
}
})(window);
}
Performance Considerations
- Use
classListinstead ofclassNamefor better performance when modifying individual classes - Cache DOM elements when you need to access them multiple times
- Use event delegation for better performance with many similar elements
- Avoid inline event handlers in production code for better maintainability
CSS-JS Coordination
Ensure your CSS and JavaScript work together smoothly:
/* Use CSS transitions for smooth class changes */
.element {
transition: all 0.3s ease;
}
.element.active {
transform: scale(1.1);
background-color: #007bff;
}
.element.hidden {
opacity: 0;
visibility: hidden;
}
// JavaScript for smooth transitions
element.classList.add('active'); // CSS transition will handle the animation
Conclusion
Changing element classes with JavaScript is a fundamental skill for creating interactive web pages. The modern classList API provides the most flexible and efficient way to manipulate classes, while event listeners offer robust control over when and how classes change. Remember to consider browser compatibility for older browsers and use performance optimization techniques like caching elements and event delegation for better user experience. By combining these techniques with CSS transitions, you can create smooth, responsive interfaces that enhance user interaction without page reloads.