Go back to home page of Unsolicited Advice from Tiffany B. Brown

Class manipulation with classList

Many features of JavaScript/DOM frameworks are being incorporated into the browser natively. In my last post, I talked about the Selectors API. In this one, we'll look at classList.

classList makes it much easier to work with elements and class names. With it, you can:

  • Add, remove, and toggle classes;
  • Retrieve the class name at a specified index; or
  • Check whether an element contains a particular class.

classList returns a DOMTokenList — a space-separated list of tokens — containing the class names currently applied to the element.

Its syntax is simple: elementNode.classList.methodname(arg) where methodname is either add(), remove(), toggle(), contains(), or item() and arg is either a numeric index (in the case of item() ), or a class name. classList also has a length property, which tells you how many class names have been applied to the element.

Let’s look at some examples.

LetsPretendWeAreBuildingANewsSite.net

Pretend we’re building the home page of a news web site. This means we have lots of lists of stories, each styled slightly differently based on their section and prominence. We're also going to allow users to hide some lists of headlines. Which ones can be hidden is determined by a class name.

One of our home page lists, then, has three class names: hardnews (as opposed to say, celebrity gossip), business, and removable. The markup looks like this:

<ul id="bizheadlines" class="hardnews business removable">
    <li>Coca-Cola posts a Q3 profit</li>
    <li>Justin Timberlake invests in MySpace</li>
    <li>Google tries to get social (again) with Google+</li>
    <li>Southwest and AirTran airlines to merge</li>
    <li>Stocks can't decide whether they're up or down</li>
</ul>

Retrieving all classes on an element

If we wanted to retrieve all class names on our list, that's an easy enough task:

var biz = document.getElementById('bizheadlines'); // could also use document.querySelector('#bizheadlines');
var bizclasses = biz.classList;
console.log(bizclasses)

The code above would write hardnews business removable to the JavaScript console.

Retrieving all class names on an element is only somewhat useful. You would typically use this to test whether the element has a class at all, or whether classList is supported by the browser. If document.body.classList == undefined, for example, you know that it is unsupported in that browser.

Retrieving a class name by index

Instead, let’s try retrieving the third class name in the list. Here we’d use item(n), where n is an integer between 0 and the number of classes minus 1 (element.classList.length - 1).

var biz = document.getElementById('bizheadlines');
var bizclasses = biz.classList;
console.log( bizclasses.item(2) )

Executing the above writes removable to the console. If a class name does not exist at that index, the value of bizclasses.item(2) would be null instead.

Adding a class name

Now, the real fun of classList is the ability to add, remove and toggle the class names of an element. So let’s say one of our users wants to hide our list. They can do that because we’ve specified that it is removable with the removable class. But removable only says that it can be removed. We need to add another class (hide) in order to remove the list from view. Meet the add() method.

var biz = document.getElementById('bizheadlines');
biz.classList.add('hide');

In order for this to work, of course, .hide must be defined in our CSS: .hide{display:none;}.

Note that you can’t add a list of space-separated values to classList. For example, document.body.classList.add('sports sectionfront') won’t work. You must instead add them one at a time, or use className.

Removing a class name

To remove a class name (maybe our user wants to restore that list of headlines) use the remove() method. It, like add(), accepts a class name as a parameter.

var biz = document.getElementById('bizheadlines');
biz.classList.remove('hide');

Here too, you need to remove classes one by one, or use className.

Toggling classes

Of course, since we’re just adding and removing a class name, we could just toggle it. As you’d expect, this is where we’d use the toggle() method.

var biz = document.getElementById('bizheadlines');
biz.classList.toggle('hide');

If the element does not contain the hide class, toggle() will add it. If it does, invoking toggle() will remove it.

Checking whether a particular class exists

What if you wanted to show a message only when the user tries to close a hard news headline list? Then you would want to check whether the element in question has a hardnews class. This is where the contains() method comes in handy.

// Get all removable lists of headlines
var removable = document.querySelectorAll('.removable');

var clickhandler = function(e){
    // if the current target has a 'hardnews' class
    if( e.target.classList.contains('hardnews') ){
        var cont = confirm("Hiding this will make you a less informed citizen. Are you sure?");

        if(cont){
            e.target.classList.add('hide');
        } else{}
    }
}

// apply the click handler
for( var i=0; i < removable.length; i++){
    removable[i].onclick = clickhandler;
}

In the above example, we have applied a click handler to all removable lists. If a user tries to remove a hard news section, we ask for confirmation. If they confirm, we will hide it. Otherwise, we won't.

See classList in action

Though decidedly not a news web site home page, you can get a sense of how these methods can be used together in this classList demo.

Browser support

Here's the caveat: classList is not yet supported in iOS Safari, or Internet Explorer 9 (it's unclear whether support will be available in IE10). In those cases, you will still need to use className or getAttribute('class') and manipulate it using JavaScript string methods and regular expressions.