Exploring the classList API

Web & App Developer

Since the creation of HTML and the birth of the first websites, developers and designers have tried to customize the look and feel of their pages. This need became so important that a standard, called CSS, was created to properly manage style and separate it from the content. In today’s highly interactive websites, you often need to add, remove, or toggle class names (usually referred to as “CSS classes”). Historically, dealing with these changes in JavaScript was slightly complicated because there were no built-in methods to perform these actions. This was the case until HTML5 introduced the classList API. In this article, we’ll discover how this API works and the methods it provides.

Note: The term “CSS classes” is often used to refer to class names. These are the strings you put inside the class attribute of an element. However, there is an interesting article suggesting that the term is incorrect and you should avoid it. For the sake of brevity, in this article I’m going to use the term “classes” as a shortcut for “class names”.

What is the classList API?

The classList API provides methods and properties to manage class names of DOM elements. Using it, we can perform operations such as adding and removing classes, or checking if a given class is present on an element. The classList API exposes these methods and properties via an attribute of the DOM element, called classList. This attribute is of type DOMTokenList, and contains the following methods and properties:

  • add(class1, class2, ...): Adds one or more classes to the element’s class list.
  • contains(class): Returns true if the list of classes contains the given parameter, and false otherwise.
  • item(index): Returns the class at position index, or null if the number is greater than or equal to the length of the list. The index is zero-based, meaning that the first class name has index 0.
  • length: This is a read-only property that returns the number of classes in the list.
  • remove(class1, class2, ...): Removes one or more classes from the element’s class list.
  • toString(): Returns the element’s list of classes as a string.
  • toggle(class[, force]): Removes the given class from the class list, and returns false. If the class didn’t exist, it is added, and the function returns true. If the second argument is provided, it’ll force the class to be added or removed based on its truthiness. For example, setting this value to true causes the class to be added, regardless of whether or not it already existed. By setting this value to false, the class will be removed.

If you’re familiar with jQuery, you may think that the add() and remove() methods perform the same operation on multiple classes by passing a list of space-separated class names (for example add("red bold bigger")). This is not the case. To add or remove more classes at once, you’ve to pass a string for each classes (for example add("red", "bold", "bigger")). As I pointed out, the toggle() method has an optional argument that we can use to force a given action. In other words, if the second parameter of toggle() is false, it acts as the remove() method; if the second parameter is true, it acts as the add() method.

Now that we’ve described the methods and the properties of this API, let’s see some examples of it in action. Each of the code samples shown below will perform an action assuming the presence of the following HTML element on the page.

<span id="element" class="description"></span>

Adding a Class

To add the class name “red” to the class attribute of the element, we can write the following:

document.getElementById('element').classList.add('red');
// class="description red"

To add multiple classes, for example “red” and “bold”, we can write this:

document.getElementById('element').classList.add('red', 'bold');
// class="description red bold"

Note that if one of the provided classes was already present, it won’t be added again.

Removing a Class

To delete a class, for example “description”, we would write the following:

document.getElementById('element').classList.remove('description');
// class=""

To remove multiple classes at once, we write:

document.getElementById('element').classList.remove('description', 'red');
// class=""

Note that an error is not thrown if one of the named classes provided wasn’t present.

Toggling a Class

Sometimes we need to add or remove a class name based on a user interaction or the state of the site. This is accomplished using the toggle() method, as demonstrated below.

document.getElementById('element').classList.toggle('description');
// class=""

document.getElementById('element').classList.toggle('description');
// class="description"

Retrieving a Class

The classList API provides a method of retrieving class names based on it’s position in the list of classes. Let’s say that we want to retrieve the first and the third classes of our element. We would write the following:

document.getElementById('element').classList.item(0);
// returns "description"

document.getElementById('element').classList.item(2);
// returns null

Retrieving the Number of Classes

Although not very common, there are cases where we may need to know the number of classes applied to a given element. The classList API allows us to retrieve this number through the length property as shown below:

console.log(document.getElementById('element').classList.length);
// prints 1

Determine if a Class Exists

Sometimes we may want to execute a given action based on the presence of a certain class. To perform the test we use the contains() method in the following fashion:

if (document.getElementById('element').classList.contains('description')) {
   // do something...
} else {
   // do something different...
}

Returning the Class List as a String

To return the list of classes as a string, we can use the toString() method, which is shown below.

console.log(document.getElementById('element').classList.toString());
// prints "description"

document.getElementById('element').classList.add('red', 'bold');
console.log(document.getElementById('element').classList.toString());
// prints "description red bold"

Browser Compatibility

The classList API is widely supported among desktop and mobile browsers except for Internet Explorer. IE began supporting this API starting in version 10. More specifically, you can use this API in Chrome 8+, Firefox 3.6+, Internet Explorer 10+, Safari 5.1+, and Opera 11.5+. As we’ve seen the classList API is very straightforward and, as you may guess, polyfilling it is not difficult. Creating your own polyfill should be straightfoward, but if you want something that already exists, you can use classList.js by Eli Grey.

Demo

This section provides a simple demo that allows you to experiment with the concepts explained in this article. The demo page contains two basic fields: a select element containing the methods and properties exposed by the API, and a textbox where we can write parameters to pass. As you’ll see, the demo doesn’t explicitly call the methods, but instead uses a simple trick (the use of the JavaScript apply() method), resulting in fewer lines of code. Because some browsers don’t support the API, we perform a check, and if it fails we display the message “API not supported”. If the browser does support the classList API, we attach a listener for the click event of the button so that once clicked, we execute the chosen method.

A live demo of the code is available here.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>ClassList API Demo</title>
    <style>
      body
      {
        max-width: 500px;
        margin: 2em auto;
        font-size: 20px;
      }

      h1
      {
        text-align: center;
      }

      .hidden
      {
        display: none;
      }

      .field-wrapper
      {
        margin-top: 1em;
      }

      #log
      {
        height: 200px;
        width: 100%;
        overflow-y: scroll;
        border: 1px solid #333333;
        line-height: 1.3em;
      }

      .button-demo
      {
        padding: 0.5em;
        margin: 1em;
      }

      .author
      {
        display: block;
        margin-top: 1em;
      }
    </style>
  </head>
  <body>
    <h1>ClassList API</h1>

    <h3>Live sample element</h3>
    <div id="showcase">
      &lt;span id="play-element" class="description"&gt;&lt;/span&gt;
    </div>

    <h3>Play area</h3>
    <div>
      <div class="field-wrapper">
      <label for="method">Methods and Properties:</label>
        <select id="method">
          <option value="add">add()</option>
          <option value="contains">contains()</option>
          <option value="item">item()</option>
          <option value="length">length</option>
          <option value="remove">remove()</option>
          <option value="toString">toString()</option>
          <option value="toggle">toggle()</option>
        </select>
      </div>
      <div class="field-wrapper">
        <label for="parameter">Parameters (use spaces for multiple parameters):</label>
        <input type="text" id="parameter"></input>
      </div>

      <button id="execute" class="button-demo">Execute</button>
    </div>
    
    <span id="d-unsupported" class="hidden">API not supported</span>

    <h3>Log</h3>
    <div id="log"></div>
    <button id="clear-log" class="button-demo">Clear log</button>

    <span id="play-element" class="description"></span>

    <script>
      if (!'classList' in document.createElement('span')) {
        document.getElementById('c-unsupported').classList.remove('hidden');
        document.getElementById('execute').setAttribute('disabled', 'disabled');
      } else {
        var playElement = document.getElementById('play-element');
        var method = document.getElementById('method');
        var parameter = document.getElementById('parameter');
        var log = document.getElementById('log');
        var showcase = document.getElementById('showcase');

        document.getElementById('clear-log').addEventListener('click', function() {
          log.innerHTML = '';
        });

        document.getElementById('execute').addEventListener('click', function() {
          var message = method.value;

          if (method.value === 'length') {
            message += ': ' + playElement.classList[method.value]
          } else {
            var result = playElement.classList[method.value].apply(playElement.classList, parameter.value.split(' '));

            showcase.textContent = playElement.outerHTML;

            if (method.value === 'add' || method.value === 'remove' || method.value === 'toggle') {
              message += ' class "' + parameter.value + '"';
            } else {
              message += ': ' + result;
            }
          }
          
          log.innerHTML = message + '<br />' + log.innerHTML;
        });
      }
    </script>
  </body>
</html>

Conclusions

In this article, we’ve learned about the classList API, its methods, and its properties. As we’ve seen, this API helps us in managing the classes assigned to a given element – and it is very easy to use and. This API is widely supported among desktop and mobile browsers, so we can use it safely (with the help of a polyfill if needed). As a last note, don’t forget to play with the demo to gain a better grasp of this API and its capabilities.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://wpfreelance.in/ WP Freelance

    Hi Aurelio, Definitely a short tutorial and a great resource,
    I am sure in next few days we will see the more advanced use case examples,

    Thanks for sharing
    Gabu Singh

    • Aurelio De Rosa

      Hi. This API is as simple as it appears, so there aren’t advanced user cases. It’s a nice feature that you can use to create nice effect playing with CSS.

  • http://alfy.me/ Ahmad Alfy

    Hey Aurelio, thanks for the interesting intro and the polyfil. Definitely worth using now.
    Just a tiny thing because I got confused. When talking about jQuery: add(), remove(), toggle() I think you meant addClass(), removeClass(), toggleClass() ? because otherwise it will be adding, removing, toggling visibility of elements!

    • Aurelio De Rosa

      Hi Ahmad. Good catch! Sure I meant that, but you’re right I actually didn’t write it :) I’ll fix it soon.

      • http://alfy.me/ Ahmad Alfy

        I read it again slower and figured out what you meant. Apologies for the confusion :)

  • mooduino

    Hi. Nice article. I get an error when I click on the demo link, though.

    • Aurelio De Rosa

      What error?

      • mooduino

        It was a server error. It’s not doing it now.

        • Aurelio De Rosa

          Oh…good to know. Thank you for the reply.

          • mooduino

            I wish I’d taken a screenshot really.