Selectors in JavaScript – IDs, Data Attributes, or Classes

3/20/15

I did a guest lecture Tuesday night at Ignition, a coding school run by Spark Boulder that prepares students for their first coding internship. It was fun and I learned a lot about how to improve lecturing abilities. I also got a lot of good questions and one question that I didn’t think I answered well enough, so I thought I’d elaborate.

If you have no interest in JavaScript, you may want to stop reading now. 🙂

The question:

Should we only select DOM elements by ID in JavaScript? If so, why are you using only classes?

This is a great question.

In most cases, it makes sense to separate JavaScript (JS) selectors from stylesheet selectors. This allow you to change presentation (styles) without breaking behavior (JS), but are IDs the best way to do this? I say no. Below I walk through several reasons why IDs may not be the best solution and I suggest an alternative.

Some Reasons I Don’t Use IDs As JavaScript Selectors

IDs Can Only Be Used One Time On A Page

Let’s say we have a group of repeating elements to which we want to bind a click. With a class it is easy, but with an ID you’d need to iterate the ID name (#element01, #element02, …,#elementN). This isn’t a big deal when using a loop to create the HTML. In the jQuery/JavaScript, however, instead of using a simple selector like $(‘.element’) for a class, you’d need to use a more complex one like $(‘#element01, #element02, …, #elementN’). And if you have a dynamic number of elements? Then you’d need an even more complex selector like $(“[id^=element]”). This selector grabs any element that starts with the ID element.

No big deal. Right? I guess.

The complexity isn’t that bad and you still get the benefit of separating behavior and presentation, but what if you need to target something inside the repeating element. A good example of this is an accordion; you know, a list of items (siblings) that expand on click and collapse when a sibling is clicked. With jQuery, you’d add a click event to an item where [id^=element]. The element that is clicked can be used to find it’s sibling, but if you’re only using IDs, you’d also have to add another cumbersome, iterating ID (e.g. id^=sibling) to the sibling (#sibling01, #sibling02) .

You can probably see where I’m going with this,  given complex and dynamic functionality, you’ll find it increasingly difficult to iterate every element that you want to select with JavaScript.

Some people like complexity, but let’s say for some reason you can’t loop the HTML to easily make the IDs unique; for instance, when you’re not using real data. Prepare to waste time. And when the client asks to change the order of the elements? More time gone. And what about when your function stops working all together because you had two identical IDs? Not good. And what about when you accidentally bind #elementary and #elemental when you only thought you were binding #element+number. Yes, another debugging problem.

The fact that you can only use IDs once means that your code is more complex and difficult to maintain.

You Can Only Add One ID Per Element

Let’s say I add some complex animation to an element by ID. Later, I realize I want to add some unrelated analytics to that element as well. I could bind it to the same ID, but that could pose a problem if it also needs to be added to other elements on the same page. With IDs, there is no way I can add another selector to keep these unrelated behaviors separate.

I Like To Write Stuff To Be Repeatable

Let’s say I write a block of code using an ID and then I decide I want to repeat it later. If I used IDs I’d have to copy and paste the HTML, make the IDs unique, and go back to update the JS. Why not just write it to be repeatable the first time? You can’t do that with IDs.

Presentation And Behavior Are Often Interconnected

Good website design often includes changes to style based on the state of an element (open, closed, focused, clicked, etc.). An extremely easy way to do this is to use the jQuery functions .addClass(), .removeClass(), and .hasClass(). By its very nature, this feature requires that we manipulate classes with JS.

Many times, presentation and behavior are interrelated and separating them in some cases isn’t good.

I Like To Make Selectors Easily Searchable In JavaScript

I’ve worked on several big sites. These were built and maintained by many developers (in house and out) and they have a lot of moving parts. When adding and changing functionality, these sites have many files that affect the elements of any page—sometimes files on top of files.

Let’s say I need to make a change to a repeating element. It would be nice to search all files for the element’s selector (#element01) and then easily update; however, remember I had to use an iterating ID and a cumbersome JS selector; therefore, I can’t just search all files for “.element”; instead, I need to search for just “element”. On a big site, I’ll probably find hundreds of pages that contain that string, making it very difficult to find all references to this selector in the JavaScript.

I solve this problem in two ways, (1) I try to make my selector names specific and unique, and (2) I never modify the selector name in JavaScript; for example, if the id=”element01″ I always write the JS selector as #element01, never [id^=element]. This way I can easily search for it and find anything and everything that is bound to that selector. You can’t do that with IDs on repeating elements.

A Proposed Solution

So, what if we all agreed on a solution that gets many of the benefits of using IDs while still solving the problems I introduced above? Would it be adopted? Probably not, but here goes anyways.

I submit that instead of using IDs for JavaScript, we just use classes. Ok, hear me out. If behavior and presentation are interconnected, we attach both CSS and JS to the same selector, but we never alter a selector’s class name in JS to make them easily searchable and update-able. Whenever we make a change to presentation, we just search the whole site for that string and update any JS attached to it.

Whenever possible, we separate behavior and presentation by using a naming convention to identify classes that are only used as JS selectors. For instance, we add .js to the beginning of selectors only used for behavior (e.g. .jsElement, .jsSibling, etc.).

This simple rule would solve all our problems. What do you think?

Rebuttal

I’m sure there are things I didn’t take into account above. I’d love to hear your comments below. In an attempt to rebuttal some of the easy responses to my proposal above, I’ve included a couple thoughts here.

I know someone is thinking, “but classes are slower selectors than IDs.” Yes, but I’d argue it is negligible. You’re still talking milliseconds. I heard someone say once that when you write code, write it as elegant as possible even if it occasionally sacrifices speed. Then, go back and rewrite if only if necessary (although it isn’t most of the time).

And others are thinking, “but data elements as JS selectors would be better.” The problem with data elements is that you’ll always have instances when behavior and presentation are interconnected. Why not just have one simple rule that solves all our problems, rather than using data elements except when we don’t. And data elements are slower. 🙂

What do you think? Comment below.

 

About The Author

Ben currently works as a senior developer and technical business consultant outside of Boulder, Colorado.

Read more about Ben

About Buink

Buink Web Development is a website development company founded in 2009. Although we still focus on web development, we now offer digital marketing services, web design, local SEO services, ecommerce website design, and custom logo design

Our value proposition: Buink can help you unleash the power of the internet and help your business scale with superior quality code at a competitive price and in a transparent, honest way. 

Read more about Buink

Cycle S.
Cycle S.
1709262820
Buink generously helped us optimize our Google Ads for an upcoming community event. He expertly walked us through our dashboard making precise recommendations that helped us launch a successful campaign. Google Ads were much more difficult to get going than we anticipated, so we were very grateful... for the advice.read more
Dave G.
Dave G.
1691935511
Buink is a great place to work, as well as a great place to have quality software written. I originally contracted Buink for some web development, and it worked out so well we began working together on many different projects. Definitely an honest transparent company that needs to be considered for... your software needs.read more
Dru M.
Dru M.
1616686900
Ben’s a super responsive, thoughtful, sharp and all around great guy to work with. Excellent with his trade. I’d recommend him to anyone. Thanks Ben!
Craig A.
Craig A.
1560891037
It was a pleasure to work with Ben and his team. It is rare to find such attention to high standards of coding and devops.
Lexi S.
Lexi S.
1560872174
Grateful to have Ben and his team as such a capable, reliable partner for completing client work!
Tom S.
Tom S.
1560518288
I reached out to Buink after finding Ben’s name in a local developer/consultant listing in 2017, and I have to say, it has been an absolute pleasure to work with Buink. Ben consistently understands not just the development task laid in front of him but the business application behind the task. I’ve... never felt more comfortable with a development team than I do with Buink. I truly feel Ben and his team are integral partners in the success of my business.read more
Marilyn F.
Marilyn F.
1557787674
I could not recommend Buink Web Development more highly. Ben and his team have recently developed a budgeting app for me (both web and IOS). I have had the opportunity of working with them for over a year and I am extremely happy with the results.I would say that the biggest plus for me is that I... trust Ben completely. From the very first, Ben has helped me make decisions that were in the best interest of my company. I have never felt like he is taking advantage of me. Ben does his best to keep the whole process very open and upfront. I have really appreciated that.I tell people all the time that I love my developers. And I do. I'm very happy that I chose to use Buink to develop my apps. It was the best business decision I could have made.If you are looking for someone to develop a website or app, I strongly suggest choosing Buink Web Development. They are fantastic!Marilyn Ference, President, Defend Your Money, LLCread more
James Landon B.
James Landon B.
1535420033
Great company to help with all your web design needs!
Next Reviews
js_loader

Connect with Buink

Connect with Buink via email, send us a message, or subscribe to our blog.