JavaScript
Article
By Yaphi Berhanu

Quick Tip: Add or Remove a CSS Class with Vanilla JavaScript

By Yaphi Berhanu

This article was peer reviewed by Mev-Rael and Panayiotis Velisarakos. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

Sometimes you need to add or remove a CSS class with JavaScript, and you don’t want to include an entire library like jQuery to do it.

This is useful in situations when you want your page elements to change in response to user actions.

Example uses include:

  • Showing or hiding a menu
  • Highlighting a form error
  • Showing a dialog box
  • Showing different content in response to a selection
  • Animating an element in response to a click

There are two JavaScript properties that let you work with classes: className and classList. The former is widely compatible, while the latter is more modern and convenient. If you don’t need to support IE 8 and 9, you can skip className.

We’ll start with the compatible version first.

Note: This tutorial assumes some familiarity with JavaScript concepts like functions and variables.

Modifying Classes the Compatible Way

The JavaScript className property lets you access the class attribute of an HTML element. Some string manipulation will let us add and remove classes.

We’ll access HTML elements using querySelectorAll(), which is compatible with browsers from IE8 and up.

Add a Class

To add a class, we’ll write a function that takes in the elements we want to change and adds a specified class to all of them.

function addClass(elements, myClass) {

  // if there are no elements, we're done
  if (!elements) { return; }

  // if we have a selector, get the chosen elements
  if (typeof(elements) === 'string') {
    elements = document.querySelectorAll(elements);
  }

  // if we have a single DOM element, make it an array to simplify behavior
  else if (elements.tagName) { elements=[elements]; }

  // add class to all chosen elements
  for (var i=0; i<elements.length; i++) {

    // if class is not already found
    if ( (' '+elements[i].className+' ').indexOf(' '+myClass+' ') < 0 ) {

      // add class
      elements[i].className += ' ' + myClass;
    }
  }
}

You’ll see how the function works soon, but to watch the function in action, feel free to use this CSS:

.red {
  background: red;
}

.highlight {
  background: gold;
}

…and this HTML:

<div id="iddiv" class="highlight">ID div</div>

<div class="classdiv">Class div</div>
<div class="classdiv">Class div</div>
<div class="classdiv">Class div</div>

Here are some usage examples of the function itself:

addClass('#iddiv','highlight');
addClass('.classdiv','highlight');

addClass(document.getElementById('iddiv'),'highlight');
addClass(document.querySelector('.classdiv'),'highlight');
addClass(document.querySelectorAll('.classdiv'),'highlight');

Notice that you can identify the HTML elements you want to change through a selector or you can directly pass in the elements themselves.

How Our addClass Function Works

Our addClass function first takes two parameters: the HTML elements we want to modify and the class we want to add. Our goal is to loop through each HTML element, make sure the class is not already there, and then add the class.

First, if the list of elements is empty, our function has nothing left to do, so we can get out early.

// if there are no elements, we're done
if (!elements) { return; }

Next, if we’ve chosen to identify our HTML elements through a selector such as #iddiv or .classdiv, then we can use querySelectorAll() to grab all of our desired elements.

// if we have a selector, get the chosen elements
if (typeof(elements) === 'string') {
  elements = document.querySelectorAll(elements);
}

However, if DOM elements are fed into the function directly, we can loop through them. If there’s a single DOM element (rather than a list), we’ll make it an array so we can use the same loop and simplify our code. We can tell if there’s only one element because an element has a tagName property, while a list does not.

// if we have a single DOM element, make it an array to simplify behavior
else if (elements.tagName) { elements=[elements]; }

Now that we have our elements in a format we can loop over, we’ll go through each one, check if the class is already there, and if not, we’ll add the class.

// add class to all chosen elements
for (var i=0; i<elements.length; i++) {

  // if class is not already found
  if ( (' '+elements[i].className+' ').indexOf(' '+myClass+' ') < 0 ) {

    // add class
    elements[i].className += ' ' + myClass;
  }
}

Notice we’re adding a space at the beginning and end in order to simplify the pattern we’re looking for and avoid needing a regular expression.

In any case, we’re done — you can now add a class!

Remove a Class

To remove a class, we can use the following function:

function removeClass(elements, myClass) {

  // if there are no elements, we're done
  if (!elements) { return; }

  // if we have a selector, get the chosen elements
  if (typeof(elements) === 'string') {
    elements = document.querySelectorAll(elements);
  }

  // if we have a single DOM element, make it an array to simplify behavior
  else if (elements.tagName) { elements=[elements]; }

  // create pattern to find class name
  var reg = new RegExp('(^| )'+myClass+'($| )','g');

  // remove class from all chosen elements
  for (var i=0; i<elements.length; i++) {
    elements[i].className = elements[i].className.replace(reg,' ');
  }
}

Most of this removeClass function works the same way as our addClass function; by gathering the desired HTML elements and looping through them. The only difference is the part where the class gets removed.

Here’s the class removal in more detail:

// create pattern to find class name
var reg = new RegExp('(^| )'+myClass+'($| )','g');

// remove class from all chosen elements
for (var i=0; i<elements.length; i++) {
  elements[i].className = elements[i].className.replace(reg,' ');
}

First, we create a regular expression to look for all instances of our desired class. The expression '(^| )'+myClass+'($| )' means the beginning or a space followed by myClass followed by the end or a space. The 'g' means global match, which means find all instances of the pattern.

Using our pattern, we replace the class name with a space. That way, class names in the middle of the list will remain separated, and there’s no harm done if the removed class is on the ends.

--ADVERTISEMENT--

Modifying Classes the Modern Way

Browsers from IE10 and up support a property called classList, which makes an element’s classes much easier to deal with.

In a previous article, Craig Buckler provided a list of things classList can do:

The following properties are available:

length — the number of class names applied
item(index) — the class name at a specific index
contains(class) — returns true if a node has that class applied
add(class) — applies a new class to the node
remove(class) — removes a class from the node
toggle(class) — removes or adds a class if it’s applied or not applied respectively

We can use this in preference to the clunkier className property:

document.getElementById("myelement").classList.add("myclass");

Let’s use this information to create functions that add and remove classes from all elements that match a selector.

These functions will get all desired elements, loop through them, and add or remove a class to each one.

Add Class

function addClass(selector, myClass) {

  // get all elements that match our selector
  elements = document.querySelectorAll(selector);

  // add class to all chosen elements
  for (var i=0; i<elements.length; i++) {
    elements[i].classList.add(myClass);
  }
}

// usage examples:
addClass('.class-selector', 'example-class');
addClass('#id-selector', 'example-class');

Remove class

function removeClass(selector, myClass) {

  // get all elements that match our selector
  elements = document.querySelectorAll(selector);

  // remove class from all chosen elements
  for (var i=0; i<elements.length; i++) {
    elements[i].classList.remove(myClass);
  }
}

// usage examples:
removeClass('.class-selector', 'example-class');
removeClass('#id-selector', 'example-class');

Conclusion

We’ve covered how to add and remove classes through className (the compatible way) and classList (the more modern way).

When you can control CSS classes through JavaScript, you unlock a lot of functionality including content display updates, animations, error messages, dialogs, menus, and more.

I hope this article has been helpful, and if you have any questions or thoughts, please feel free to share them in the comments.

  • Ralph Mason

    Great article, Yaphi. As a relative JS beginner, this was really fun to read and work through. At first, I was stuck on how if (!elements.length) could identify a single element, but then it dawned on me: .length is a property of an array, so if that property doesn’t exist here, this isn’t an array of elements, but a single one. Cool strategy. :-)

    • Glad you enjoyed it!

    • nnnnnn321

      Note that if (!elements.length) doesn’t actually work to test if elements is a single DOM element or a list, because some types of single DOM elements (for example, select and form elements) have a .length property, and some lists are empty.

      The removeClass() function would crash if passed an empty list, because elements.length would be zero (falsey), so the empty list would be wrapped in an array, then the for loop would end up trying to call .replace() on the undefined .className property of the empty list.

      • @nnnnnn321:disqus You’re absolutely right. I apologize for the oversight and thank you for your comment. This has now been updated in the article.

  • Thanks for showing the different ways to modify elements’ classes. One thing I’d like to point out, though, is that the use of for-loops is not necessary. There’s a much easier way to iterate over the node list that is returned by querySelectorAll – using Array.prototype.forEach on them:


    var forEach = [].forEach,
    elements = document.querySelectorAll(element);

    forEach.call(elements, function (element) {
    // Your logic here...
    });

    • You’re right. The only reason I used a for loop in this case was that I wanted the first example to be widely compatible, and I wanted to keep the second example as consistent as possible except for the addition of classList.

      Thanks for the comment! `forEach` is a very useful thing for people to know.

  • Adwardok
  • Essential read for beginners, thanks for sharing Yaphi!

  • I like Vanilla javascript or (Pure JS) as I love to call it :)

    Actually I made similar function to this one,
    I’m testing for arrays using instanceof operator which is supported by IE8 and maybe IE5+,
    I split the targeted element’s className and use indexOf (IE9+) method on resulting array to see if the class in subject is exist before adding / removing the new class

    And since we’re here, it’s good to have toggleClass function which may lead us to create a hasClass function :)

    after that we can group all these functions under one namespace (mine is called zForms or z for short)

    Regards

    • Awesome! toggleClass and hasClass are good ones too.

    • nnnnnn321

      Why are you “testing for arrays” at all in this context?

      • Well, if what you’re referring to is that querySelectorAll doesn’t return Array then you’re correct
        I was actually talking about my code which uses an modified version of querySelectorAll which returns an Array from an Array like object,

        So sorry if I confused you, I have to be more careful next time

  • Another unprofessional writing. Very poor.

    • Thanks for the feedback. If you’d like to share specifics of which parts you felt were unclear or inaccurate, that would help the readers, and I’d personally appreciate it as well.

      • nnnnnn321

        I think you can safely ignore englishextra’s comment given the lack of specific feedback. There was one error in your code: as I mentioned in a comment the other day the if (!elements.length) test doesn’t actually work, and I think that’s a bad enough error that you should update the article to fix it. But other than that I thought this was a good article for beginners.

    • James Hibbard

      Unless you can substantiate this, I’ll have to assume you’re trolling and will delete the post.

  • Vasiliy Os

    Why did you use the `!` operator before `(‘ ‘+elements[i].className+’ ‘).indexOf(‘ ‘+myClass+’ ‘)` expression, compared with the `-1` int?

  • Thomas Vanier

    Thanks Yaphi for the great article. Both “compatible” addClass and removeClass could be implemented using the same regular expression (no indexOf).


    function addClass(element, myClass) {
    var reg = new RegExp('(^| )'+myClass+'($| )','g');

    if (!element.className.match(reg)) { // or if (!reg.test(element.className)) {
    element.className += ' ' + myClass;
    }
    }

    function removeClass(element, myClass) {
    var reg = new RegExp('(^| )'+myClass+'($| )','g');

    element.className = element.className.replace(reg, ' ');
    }

    • Glad you liked it! Very true about the regex. The only reason I used indexOf in the first function is that I didn’t need to do a replacement there, and so indexOf was a tiny bit more readable. On the other hand, I like the consistency of using the same regex, so thanks for bringing it up.

Recommended
Sponsors
Get the latest in JavaScript, once a week, for free.