Should you use IDs in CSS Selectors? [Discussion]

Split from previous topic to avoid derail in a newer campers help thread :slight_smile:

Original derail:

CSS Lint would argue you shouldnā€™t use IDs for CSS selectors:

http://oli.jp/2011/ids/

Follow-up:

So, there is some disagreement about the use of IDs in CSS selectors. See the link above and the one in @janschreiberā€™s reply below.

Iā€™m interested in hearing thoughts from others in the community :slight_smile:

1 Like

It sure does @JacksonBates , but I think, at this stage, a good way to learn the difference between ID and class is just to use them.

I was going to mention it but i didnā€™t want to over-complicate things.

Dontā€™cha think?

@JacksonBates Others would argue that that is ā€œabsolutely the most wrong advice I have ever heard in my life with regard to how to author CSS.ā€ https://2002-2012.mattwilcox.net/archive/entry/id/1054/

4 Likes

tbh if it wasnā€™t for lint nagging me all the time iā€™d just use the idā€™s.

When I think I know what Iā€™m doing and I want to style a unique element on a static page, I just ignore this specific CSS Lint warning. Why add a class that applies to only one element? I think this warning is meant to prevent people from styling several elements individually when itā€™s easier to give them the same class. Not 100% sure, though.

1 Like

I think its also to make sure that all rules in the CSS are re-usable, which is kind of the same thing. But if you think how bootstrap works, you just pick a class and apply it to something like choosing your style off a menu. Quite efficient for itā€™s purpose, but absolutely pointless if you just want to apply something unique to an element.

2 Likes

Yeah, maybe.

When I first started learning CSS about 8 years ago I actually found the difference between IDs and Classes quite confusing. I think I would have found it easier to understand if someone had said to me ā€˜use classes to apply CSS and use IDs to hook JavaScript / jQuery events to and define form elementsā€™.

That said - itā€™s probably pointlessly nit-picky to raise the ā€˜CSS Lint says noā€¦ā€™ idea in a newbie thread like I did! (Hence the derail thread :slight_smile: )

1 Like

Probably! but a good derail non the less. Iā€™m interested to see the consensus myself.

Every time I see those errors in my editor it chips a little bit more off my soul so I end up changing things even though I think CSS shouldnā€™t be overly opinionated about it.

I mean if my <section> has an ID, which they nearly always do, why shouldnā€™t I use that instead of adding another class? If it was a Wordpress theme where a user could make use of striped sections by applying a class then great, but I know that iā€™ll never use that kind of logic in my weather app so now iā€™ll just have to add that class to get rid of the error. Not more efficient in that case is it.

1 Like

Preferring classes over ids as CSS selectors is helpful for the same reason as preferring flat unnested selectors, or avoiding !important property values: it simplifies your CSS code and makes it easier to maintain. CSS has rules that determine the priority of a given selector, and keeping things as flat and simple as possible will make it easier for you to change your stylesheets in the future.

That said, Iā€™m not convinced that CSS and JavaScript using the same IDs is a serious problem. I guess it could be nice to have one less thing to worry about. But renaming CSS selectors from .old-name to .new-name or from #id to .class should be trivial compared to whatever refactors you are doing in your HTML or JavaScript.

I agree its trivial to change, especially in the few small apps I have produced so far. Sometimes though it just makes sense to use the ID in CSS so Iā€™m wondering why the standard has this opinion when a best practice would do. Having a couple of IDā€™s in the style sheet doesnā€™t really make it any harder to maintain I donā€™t think. Iā€™m sure its different for big apps, but I have zero experience there!

Welcome to the forum too :thumbsup:

1 Like

Perhaps I should have said it backwards:

In regards the oli.jp article from this threadā€™s original post ā€” Iā€™m not convinced that JavaScript and CSS using the same IDs is a serious problem, because rewriting CSS should be fairly trivial compared to rewriting the JavaScript.

However, the overall point that you should generally use classes instead of IDs is still valid: If all your CSS selectors are single, unnested classes, then thereā€™s less confusion about which selector takes precendence, because there are fewer tiers of priority to worry about. Especially for people new to CSS, itā€™s really easy to let things get too complicated, so suddenly you canā€™t figure out why whatever styles youā€™re writing arenā€™t working. Itā€™s a problem I ran into a few years ago. I couldnā€™t figure out WHY THIS TEXT ISNā€™T TURNING RED and no one on Stack Exchange answered my question, and it drove me crazy. But the problem was that I was writing selectors which mixed too many layers of nested elements and selector types, making it very difficult to override previous styles even with the !important property tag.

Selecting an ID instead of a class wonā€™t make your computer explode. Occasionally, I will still use an ID as a CSS selector if itā€™s already there for JavaScript events or for use in a URL fragment. But programming is already tricky, and you donā€™t want to make things harder for yourself than you have to. And using only classes, with as few nested selectors as possible, is one easy rule of thumb to help keep things simple.

So yeah, itā€™s good advice. You just donā€™t have to be too religious about it.

3 Likes

I found the articleā€™s arguments unconvincing, and that my quality of life improved when I turned that linter warning off. If someone is really so against it, Iā€™d have a hard time wanting to convince them otherwise, though. I have only been using ids as namespaces in Sass rather than relying on them for selectors.

As someone who was just put in charge of and completed the re-skinning of my companyā€™s 15+ year old application, I hate classes in CSS. Perhaps itā€™s just the way they were used by our team in that we had classes like:

.color_1 {}
.color_2 {}
.color_3 {}
.color_4 {}

Then, those classes were slapped all throughout the app willy-nilly when someone wanted a certain element to be a certain color. Great, it made adding new things and styling them quickly. However, when it came time for me to change color schemes throughout an entire app and I changed that color_1 to some other subtle color, it had far-reaching ramifications everywhere. I spent days untangling ugly CSS class selectors and editing 75 or 80 individual HTML pages.

So I guess the question is, ā€œWould that task have been easier if the CSS used fewer classes and more ids?ā€ Probably not, but I can tell you they didnā€™t make life any easier either.

Overall, Iā€™d say that I just wish I could turn off the cascade part of CSS and force it to force me to be very precise with my selectors. Iā€™d rather write 2 or 3 times the lines of CSS if I can know for certain what each selector does and does not do. I am especially fond of the new component based architecture used by a few of the big frameworks and especially Angular 2 which has a separate .css file for each component, so I can contain the leakiness of CSS to one file/component. That way my general styles.css file can be very small.

Even better yet, if Bootstrap can get me a halfway decent looking, functional page I can skip CSS altogether and move on without the frustration!

@matty22 a solution might be to use something like sass or less. I say this mostly because you can use variables so things like colors could all be defined in one file and those variables can then be used throughout the rest of the styling. Should a color ever need to change, you need to only change it once in the colors file. Iā€™m not sure if this is a best practice, but it makes sense in my head.

Yeah, the pre-processors would work great. Iā€™d wager that when this app was originally built those technologies didnā€™t exist. We also donā€™t have a build process, so using one of the pre-processors would force us to add a build process. Not likely to happen anytime soon with this version of the application.

We are about to begin a rewrite from scratch in Angular 2, so weā€™ll obviously be forced to institute a build process and I believe the plan is to use Sass for our CSS processing.

Thereā€™s nothing wrong with using id ā€˜s per se. # selector is just a tool.

The real questions are:

  • is your code easy to reason about (how much time a new developer needs to be familiar with the codebase)?
  • how much time it takes to introduce a new feature (does the development time grows with each new feature)?
  • how much time and effort it takes to change something (does changing one thing often breaks something else in the code)?
  • can multiple people work on the codebase without conflicts?

Thereā€™s no way of building a successful web project without a good system or methodology.

Letā€™s look at an example:
We want all paragraph text to be blue except the last one which should be red.

<p>first</p>
<p>second</p>
<p>third</p>

The simplest way to do it is add id to the last paragraph:

<style>
  p {
    color: blue;
  }

  #last {
    color: red;
  }
</style>

<p>first</p>
<p>second</p>
<p id="last">third</p>

It works. Letā€™s say we want to change color of the text of each paragraph to green when hovered over. Seems simple:

<style>
  p {
    color: blue;
  }

  #last {
    color: red;
  }
  
  p:hover {
    color: green;
  }
</style>

<p>first</p>
<p>second</p>
<p id="last">third</p>

Bummer. The last paragraph is still red when hovering over it. id selector has greater specificity than class + pseudoclass. Letā€™s fix it:

<style>
  p {
    color: blue;
  }

  #last {
    color: red;
  }
  
  p:hover {
    color: green;
  }
  
  #last:hover {
    color: green;
  }
</style>

<p>first</p>
<p>second</p>
<p id="last">third</p>

Now it works. But thereā€™s another requirement: The text color should be yellow instead of green when hovering over. Easy:

<style>
  p {
    color: blue;
  }

  #last {
    color: red;
  }
  
  p:hover {
    color: yellow;
  }
  
  #last:hover {
    color: green;
  }
</style>

<p>first</p>
<p>second</p>
<p id="last">third</p>

Bummer. Last paragraph is still green. The rule for hovering is in two places: one for p and one for #last . We need to change the latter as well:

<style>
  p {
    color: blue;
  }

  #last {
    color: red;
  }
  
  p:hover {
    color: yellow;
  }
  
  #last:hover {
    color: yellow;
  }
</style>

<p>first</p>
<p>second</p>
<p id="last">third</p>

Conclusion: Weā€™ve had 3 elements and two new requirements. In both implementations we had to do some debugging to make it work. What if there were hundreds of elements to look after? This way of coding does not scale and is counter-productive.

Letā€™s use BEM methodology instead:

<style>
  :root {
    --color-primary: blue;
    --color-complement: green;
    --color-emphasis: red;
  }
  
  .discussion__opinion   {
    color: var(--color-primary);
  }
  
  .discussion__opinion:hover {
    color: var(--color-complement);
  }
  
  .discussion__opinion--significant {
    color: var(--color-emphasis);
  }
</style>

<div class="discussion">
  <p class="discussion__opinion">first</p>
  <p class="discussion__opinion">second</p>
  <p class="discussion__opinion discussion__opinion--significant">third</p>
</div>

Thereā€™s initial overhead related with giving a class to each html element, but now their roles are clear. Because we use only single classes as selectors, we can be pretty confident that our code will work as expected when introducing new features as each selector has equal specificity. By using CSS variables, changing the existing styles is a matter of modifying one line of code. And naming convention that clearly separates different parts of the project makes collaboration easy.

Should you use BEM? Not necessarily, but you certainly should get familiar and use some well-established methodology even in a simple project to develop good habits. And if you get stuck, people will be more willing to help you when your code is easy to read, especially if theyā€™re acquainted with the methodology you use.

6 Likes