Using the Element classList to manage classnames in HTML5
January 19, 2016Working with class names in your DOM has been a real breeze much thanks to jQuery class methods and the refined selectors that jQuery provides. Adding and removing class names in vanilla JavaScript has traditionally not been that easy. It has not been really difficult, just cumbersome. The Element.classList changes this radically and if you have some basic experience with web development then the interface of the DOMTokenList will make you feel right at home.
If you didn’t use jQuery you would have to use setAttribute which makes perfect sense and is easy to use. The problem comes when you want to add more classes to your element. Adding is easy, you retrieve the class string with getAttribute and then concatenate the classnames you which to add. Fairly easy but not very intuitive to use and if you only want to remove a classname then you have to either use a regular expression or split the string on the space character and check against the classname value and then re-concatenate the string. To remove all classnames you would just remove the class attribute all together.
To illustrate I’ve written up a simple example in “pre html5” JavaScript, jQuery and modern JavaScript that sets an active class on a button when clicked. Normally back in the day you would use the ID attribute to select the actual button element in this case, but to be more progressive I’ll go through the data attribute and assume that all turbo buttons should have the same behaviour.
// The button element we want to change classnames on
<button type="button" data-btn="turbo" class="turbo-btn">Turbo on</button>
// Plain JavaScript that works in pretty much all browsers including IE6 and above
var buttons = document.getElementsByTagName('button');
for(var index in buttons) {
if(buttons[index].hasAttribute('class')) {
var button = buttons[index];
var class_names = button.getAttribute('class');
if(class_names.match(/turbo-btn/i)) {
button.addEventListener("click", function(event) {
if(class_names.match(/active/i)) {
class_names = class_names.replace('active', '');
this.setAttribute('class', class_names);
} else {
class_names = this.getAttribute('class') + ' active';
this.setAttribute('class', class_names);
}
}, false);
}
}
}
// Using jQuery and works pretty much in all browsers
$('button[data-btn="turbo"]').click(function(event) {
event.preventDefault();
$(this).toggleClass('active');
});
// Plain JavaScript the modern way, supported in a few browsers
// Example 1: Takes the first element found in the dom and assigns the click event.
// Useful for ID selectors or when there is only on element that should be retrieved
document.querySelector('button[data-btn="turbo"]').addEventListener("click", function(event) {
this.classList.toggle('active');
}, false);
// Example 2: If you want to assign the click event to multiple elements you could use querySelectorAll
// and then loop through the NodeList returned by querySelectorAll
var btn_list = document.querySelectorAll('button[data-btn="turbo"]'),
i = 0,
l = btn_list.length;
for (i; i < l; i = i + 1) {
btn_list[i].addEventListener("click", function(event) {
this.classList.toggle('active');
}, false);
};
As you can see JavaScript and the support for JavaScript in browsers has come a long way in the last 10 years. Of course the “pre html5” snippet could be abstracted away in various functions and so on and become part of your own framework, but most people would just turn to jQuery and I think the jQuery dominance has proven that. However, it is a new era now with single page applications and incredible powerful frameworks as Ember, React and Angular that makes many task so much easier compared to build the same things with jQuery. If you are able to target “evergreen browsers” building your average website then you might not need jQuery and save the user some bandwidth and loading time.
Looking closer at the DOMTokenList and comparing it with the functionality that jQuery provides for working with classes you’ll find them almost identical. The information below is taken from Mozilla Developer Network and I think it speaks for itself. Using the length
property and the methods item, contains, add, remove and toggle
makes it very easy to work with element classnames without using jQuery or writing a lot of glue code functions.
DOMTokenList.length
//Read only, is an integer representing the number of objects stored in the object.
DOMTokenList.item()
//Returns an item in the list by its index (or undefined if the number is greater than or equal to the length of the list, prior to Gecko 7.0 returned null)
DOMTokenList.contains()
//Returns true if the underlying string contains token, otherwise false
DOMTokenList.add()
//Adds token to the underlying string
DOMTokenList.remove()
//Removes token from the underlying string
DOMTokenList.toggle()
//Removes token from string and returns false. If token doesn't exist it's added and the function returns true
Of course there are a lot of factors to consider depending on what you are building, if to only use vanilla JavaScript, jQuery or some of the new frameworks. I’ve started to use more and more vanilla JavaScript which has increased my knowledge of JavaScript and made my websites, widgets and snippets easier to maintain and most of the time easer to build, with better performance as a bonus.