DEV Community

Cover image for Reasons Why Class Selectors Shouldn't Be Used in JavaScript!
Fatemeh Paghar
Fatemeh Paghar

Posted on


Reasons Why Class Selectors Shouldn't Be Used in JavaScript!

If you've been working in web development for any length of time, you've probably seen or written code that resembles this document.querySelector('.class').Technically speaking, there is nothing wrong with this code, and you will likely see it frequently. Nevertheless, would you be surprised if I told you that there is a far better approach to pick components in JavaScript?

Data Attributes: Introduction

Data attributes provide a better approach to choose items. For those of you who are unfamiliar, data attributes are simply custom attributes that you may add to any HTML element. They always begin with data-. For instance, you might have an element with the data-accordion-container property like this:<div data-accordion-container>.../div>
These custom data properties can also have values specified, like in the case of this div with <div data-children-count="3">...</div>.

As this essay is not about data attributes, I won't go into great detail about them; however, if you're interested, you can read my comprehensive article on data attributes. After defining data attributes, allow me to now explain why you should choose items based on them rather than classes.

Why JavaScript Selectors Work Best with Data Attributes

The first and most apparent benefit is that your selections can be more expressive. It is possible to create simple dynamic selectors by using the value of a data property in the selection. Imagine, for illustration, that when clicked, an element may switch between being active and being inactive. If we used a class-based methodology, we would require classes for active and inactive states, which would result in the following elements:

<div class="active">...</div>
<div class="inactive">...</div>
Enter fullscreen mode Exit fullscreen mode

The majority of people delete the active class and set "no class" to "active" since this is a bit complicated, especially when we have to use JavaScript to add/remove the classes. The HTML will now resemble the following, and the JavaScript code is now much cleaner:

<div class="inactive">...</div>
Enter fullscreen mode Exit fullscreen mode

The issue with this strategy is that since there is no class designating the element as active and you need to keep in mind that no class signifies active, it is no longer evident that the element is active. We can utilize data attributes to solve this issue. This would cause the environment to seem like this:

<div data-active="true">...</div>
<div data-active="false">...</div>
Enter fullscreen mode Exit fullscreen mode

So, now our HTML is very clear about what is active and what isn't, and we only need one data attribute instead of two separate classes to handle both active and inactive. This would mean that our JavaScript code will be cleaner, and we will never run into the problem of having both the active and inactive classes on the same element at the same time.

Now, this first example isn't really about class vs. data attribute selectors in JavaScript. Instead, it shows how data attributes can be used in general. The second reason, and the main reason I decided to write this email, is that using data attributes as selectors in JavaScript will keep your CSS selectors separate from your JavaScript selectors. Just imagine that in the last example, we used CSS styles for active and inactive to make the element look a certain way, and now we want to change the names of those classes to open and closed. If we use class selectors in both JavaScript and CSS, we can't tell if those classes are used in our JavaScript without going through all the code, which can be hard to do for a big project. This makes it hard to refactor CSS without worrying that it will break the JavaScript code. When you change JavaScript code, you run into the same problem. Let's say we wanted to get rid of the JavaScript code for the active/inactive toggle, and we also wanted to get rid of the active/inactive classes from our elements so we wouldn't have any dead code. Again, we can't be sure that the CSS doesn't use these classes because we used class selectors in both the CSS and the JavaScript. To check for these classes, we would have to read all of the CSS code. This may seem like a small problem, but it adds up over time and leaves you with a lot of classes on elements that may or may not be doing anything because someone took out the CSS for that class but couldn't get rid of it because JavaScript might be using that class. This also often causes bugs when the class is taken off an element but the JavaScript or CSS code depends on that class. These kinds of bugs are hard to test for and find, so they often slip through the cracks and end up in production.

Using data attribute selectors in JavaScript can address all of these issues. If data attributes are exclusively used to select elements in JavaScript, then any classes on those elements are only used by CSS. Therefore, these classes can be safely modified or removed when making changes to CSS. The same principle applies to changes in JavaScript code-data attributes can be refactored or removed without the risk of affecting CSS, as long as no data attribute selectors are used in CSS. If you prefer not to use data attributes as selectors, another option is to prefix JavaScript class selectors with "js-". For example,<div class="js-active">...</div>. This allows for the same separation between JavaScript and CSS while still using classes. Personally, I find using data attributes to be a cleaner solution than prefixing JavaScript classes, but that is just my personal preference.

Although the advantages of separating your JavaScript selectors from your CSS selectors may not appear significant initially, it is guaranteed that you will appreciate doing so greatly when your project expands or when you return to it after some months.

Top comments (2)

imthedeveloper profile image

Appreciate the sentiment here having to try and clean up an e-commerce front end theme that the Dev has utilised your exact example of adding and removing classes with js. It's horrible checking through various states to see what classes are being added removed at any point in time, couple this with different breakpoints and media queries being used it's a nightmare.

I learnt a few rough lessons in js around mutation of variables and the mess you can get into. I feel as though messing with classes can actually lead you down the same path. I like the data attribute idea, you can clearly see what is being targeted and it's before / after state options.

fruntend profile image

Сongratulations 🥳! Your article hit the top posts for the week -
Keep it up 👍