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.