Use the classList API to add, remove, toggle, check, or replace CSS classes on
an element. Unlike string manipulation, it handles whitespace and duplicate
classes for you.
The element-selection methods used in these examples are covered in this DOM query guide.
Add and remove classes
Select an element, then call classList.add() or classList.remove():
const element = document.querySelector('#foo')
if (element) {
element.classList.add('active')
element.classList.remove('hidden')
}Class names do not include the dot used in CSS selectors. Pass 'active', not
'.active'.
Both methods accept multiple class names:
element.classList.add('active', 'highlighted')
element.classList.remove('hidden', 'disabled')If the classes are in an array, spread it into the method:
const classes = ['active', 'highlighted']
element.classList.add(...classes)Adding an existing class or removing a missing class has no effect.
Toggle a class
toggle() adds a class when it is missing and removes it when it is present. It
returns true when the class is present after the call:
const button = document.querySelector('#menu-button')
const menu = document.querySelector('#menu')
button?.addEventListener('click', () => {
const isOpen = menu?.classList.toggle('open') ?? false
button.setAttribute('aria-expanded', String(isOpen))
})Pass a second boolean argument when the class should reflect a condition. This
is clearer than separate add() and remove() branches:
element.classList.toggle('selected', isSelected)When isSelected is true, the class is added. When it is false, the class
is removed.
Check or replace a class
Use contains() to test for a class:
if (element.classList.contains('active')) {
console.log('The element is active')
}Use replace() to swap one class for another:
element.classList.replace('loading', 'loaded')replace() returns false and makes no change if the old class is missing.
Change classes on multiple elements
querySelectorAll() returns a NodeList with a forEach() method. You do not
need to convert it to an array:
const accordionItems = document.querySelectorAll('.accordion-item')
accordionItems.forEach(item => {
item.classList.remove('open')
})Using classList with TypeScript
DOM queries can return null, so check the result before using it. A generic
type argument is useful when you also need properties specific to an element:
const button = document.querySelector<HTMLButtonElement>('#submit-button')
if (!button) {
throw new Error('Submit button not found')
}
button.addEventListener('click', () => {
const isLoading = button.classList.toggle('loading')
button.disabled = isLoading
})Functions that only manipulate classes can accept the broader Element type:
function setSelected(element: Element, selected: boolean): void {
element.classList.toggle('selected', selected)
}When to use className
The className property reads or replaces the entire class attribute:
element.className = 'card featured'This removes every existing class before setting the new value. Use it only when
replacing the complete class list is intentional. For individual classes, prefer
classList over string concatenation or regular expressions.
See the MDN classList reference for the full API.