How to check if an element has a class in JavaScript?
Use classList.contains to check for a class, matches for any selector and closest for ancestors, and avoid the className.includes gotcha.
Use classList.contains(). It returns true or false, and it's the modern replacement for jQuery's hasClass().
const menu = document.querySelector('.menu');
if (menu.classList.contains('is-open')) {
console.log('The menu is open');
}Pass the class name without the dot. The check is case-sensitive, so contains('Active') won't find active. It checks one class at a time; for several, use matches().
If you only check the class to flip it, skip the check: classList.toggle('is-open') does both. More on that in how to change an element's class.
Any selector: matches()
matches() takes any CSS selector, so you can check several classes, attributes or states at once:
// both classes and the attribute
card.matches('.card.is-open[data-size="lg"]');
// at least one of the classes
card.matches('.is-open, .is-pinned');It throws a SyntaxError if the selector is invalid, so be careful with class names built from user input.
Ancestors: closest()
closest() checks the element itself and then walks up its parents, returning the first match or null. It's the usual tool for event delegation, where the click target might be an icon or a <span> inside the element you care about:
document.addEventListener('click', (event) => {
const card = event.target.closest('.card');
if (!card) return;
card.classList.toggle('is-selected');
});Don't use className.includes()
className is one string with all the classes, so includes() matches parts of other class names:
// <div class="menu inactive">
el.className.includes('active'); // true, wrong
el.classList.contains('active'); // falseA regex with word boundaries doesn't fully fix it either: /\bactive\b/ matches is-active, because - counts as a word boundary. classList compares whole class names, so use it.
SVG elements
On SVG elements, className isn't a string but an SVGAnimatedString object, so el.className.includes() throws a TypeError. classList.contains() works on SVG elements the same way it does on HTML elements, which is one more reason to use it everywhere.
Maybe you don't need JavaScript
Often the check exists only to style something differently. CSS can react to the class directly:
.menu.is-open .menu__list {
display: block;
}
.card.is-selected {
outline: 2px solid currentColor;
}Keep the JavaScript for behavior, such as closing the menu on Escape only when it has is-open, and let CSS handle the looks.