CodeinWP CodeinWP

CSS Specificity Should Be (Mostly) Irrelevant

CSS Specificity Should Be IrrelevantThere have been numerous articles written by some very reputable people discussing the topic of CSS specificity.

I think it’s great if a CSS developer wants to learn the ins and outs of specificity, because it is an important aspect of how CSS works. But I’m going to put forth an argument here that CSS specificity is quite overrated and, in fact, learning about CSS specificity has the potential to degrade the quality of your code.

Who Says Classes Can’t Be Unique?

If you were to ask the average web developer to tell you the difference between a class and an ID, they’d give you the basic answer that I gave in this CSS Basics article: IDs are specific, and can’t be reused; classes are less specific and are reusable.

But many developers have taken this a step further. They reason that since the styles aren’t going to be reused, they advise you to use an ID selector. So IDs are basically reserved for unique styles that won’t apply anywhere else. This sounds fine in theory, but it is bad advice and quite silly really.

There is nothing wrong with using a class that only appears once in your stylesheet. It has basically the same effect as an ID. But when you think of the potential benefits that come from using a unique class, as opposed to a unique ID, there really is no sense in using an ID as the selector.

On its own, .element is exactly the same as #element. It doesn’t matter that the ID selector is more specific, because you’re not trying to override anything anyhow. And on top of that, the class has the potential for later reuse, and will be more likely to keep the natural cascade in place, thus keeping your code cleaner and easier to read and maintain.

Specificity Doesn’t Live in a Vacuum

CSS specificity is always relative to the rest of your CSS, and is not a relevant concept on its own. That’s why thousands of people write CSS every day without knowing much at all about specificity.

If you’ve created clean CSS that isn’t causing specificity wars (yes, this means you have to use OOCSS principles), then there’s no reason to use an ID selector, or any other selector that has high specificity.

It doesn’t matter that #element and !important have really high override abilities. It’s all relative to what else you’re doing in your stylesheet.

For example, compare this code:

.element {
  color: blue !important;
  background: green !important;
}

.element-2 {
  color: blue !important;
  background: green !important;
}

.element-3 {
  color: blue !important;
  background: green !important;
}

With the following one:

.element {
  color: blue;
  background: green;
}

.element-2 {
  color: blue;
  background: green;
}

.element-3 {
  color: blue;
  background: green;
}

Although the exact same selectors are used, and the exact same styles are being applied, it’s obvious that the first chunk of code has more weight than the second. Why? Because each line uses !important. So if these two chunks of code competed with each other, the first one would win, regardless of the cascade.

But why should they compete with each other? They shouldn’t. You should do your absolute best to avoid using !important. Each of those examples, on its own (assuming no other CSS), will produce the exact same result. So specificity (or weight, in the case of !important) is only relative to the rest of your CSS, and is not something that should really affect your CSS development much at all.

If anything, knowing that different selectors have different levels of specificity — which can often be confusing to beginners and even intermediates — should convince you beyond any doubt that OOCSS and its reliance on abstraction and class-based selectors is the superior option.

A Warning About “Learning” Specificity

In the introduction, I said that “learning” about CSS specificity could have a negative impact on your code. The reason I said that is because some may feel that giving styles higher specificity is a good thing. But it’s not.

That’s why I now strongly recommend OOCSS, which encourages using class selectors almost exclusively. Classes have low specificity, and they’re reusable on any element. If instead you choose descendant selectors (like article h2) and ID selectors, then you’re setting your code up to be far less efficient, and with a much higher chance for specificity wars.

Don’t believe me that the simple act of learning specificity can cause problems? Imagine you’re a CSS beginner and you’re creating a new web page. You know nothing about CSS, and think that the class selector is the only selector there is. You’re also aware that you can use multiple classes on a single element, but you don’t know of any other selector. The result? Although you’ll have a lot of classes in your HTML, you won’t have any specificity or cascade problems and your CSS will be easy to maintain. And this will happen even though you know nothing about specificity!

But on the other hand, if you know about varying degrees of specificity, then you’re more likely to use those more specific selectors, and use them improperly, as a crutch. And that’s where problems will arise.

No Blanket Statements

As is always the case, I am not making any blanket statements here; the “it depends” mantra applies here too.

There are rare circumstances where !important is necessary. There are circumstances, contrary to OOCSS thinking, where you have to use a descendant selector. There are cases where you’ve inherited a project and you don’t have the budget to make major changes, and it’s super practical to just use an ID selector. There are instances where a CMS dictates the markup to such an extent that understanding specificity is a huge benefit. And if you’re using a CSS preprocessor, then that could impact a lot of the concepts I’ve alluded to here.

But if you’re creating a project from scratch, and you have full control of the markup, then specificity will not matter. Specificity is under your control, and is always relative to the rest of the CSS. Therefore if you code with one level of specificity in mind in an object-oriented manner, CSS specificity will never be a factor and your code will be much cleaner and easier to maintain.

25 Responses

  1. Don’t most browsers, especially IE8 and before, target IDs much more quickly than classes when using them as a selector for DOM manipulation with a library such as jQuery?

    • Technically, yes, IDs are slightly faster. But the difference is so small that it is not worth sacrificing maintainability. For the most part, nowadays any talk on OOCSS and avoiding IDs is based on code maintainability, not performance.

    • Oh, it looks like I misunderstood your question. You’re talking about DOM manipulation. I use IDs all the time for DOM manipulation. But I usually add classes on the same elements. This way my CSS only uses classes, and my IDs are only for JS.

      I’m not sure about the performance (I would assume it’s faster to use IDs), but yes, by all means, go ahead and use IDs for JS hooks.

      • YourFriend says:

        This seems to be a great technique.
        Classes for CSS
        and
        IDs for JavaScript

        Thanks

        • Stephen Irving says:

          Yes, this is what I do also. All classes in CSS, and ID’s and some classes in JS. I use the convention of classes being written in kebab-case with classes that are used by JS being prepended with a js- (like js-is-open) and I do not mix purposes for my classes. So if a class is being used by CSS to style, I do not use it in JS I create a JS only class. That really helps with separation of concerns and preventing a change in one effecting the other. With ID’s for JS, I use snake_case with underscores. Its a helpful an easy to parse reminder that IDs go with the JS and aren’t to be mixed with my CSS where everything is kebab-case.

  2. Chris Trude says:

    This is all well and good if you are designing a 5 page website. But once you start going bigger, and having a cms, and javascript that auto-generates content. This idea is completely out the window. Also, specificity is much more powerful than !important…in fact there is never a time when you should ever use it. Using multiple level selectors and specific selectors is much more powerful and efficient.

    • Scott Vivian says:

      CMS’s generate code just fine with just classes and not IDs. Content auto-generated with Javascript should follow the same rules you use for writing your regular HTML. IDs are great for Javascript hooks, but don’t use those for styling, add a class for that.

    • I must agree with Chris.

    • I completely agree with Scott. There’s no reason why your CMS should be forced to only produce IDs and not classes. Which really gets to the heart of what I was trying to say in the classes vs. IDs section.

      There is no difference between a class and an ID if you’re not trying to override anything. In other words, specificity is irrelevant if you plan it right. Doesn’t matter how big your project is. If you have control of the markup, then you can just as easily use classes and not IDs.

    • Jorgen Kesseler says:

      I partly agree. The idea behind OOCSS (I hate the term, CSS is a query language and therefor not object oriented) works. But is hard to implement when you work on huge websites and have to deal with the crud that has build up over the past 10 years.

    • Stephen Irving says:

      No, I’m sorry but this is a really tragic misunderstanding. This methodology is specifically designed to make it easier to organize and write styles for massive projects. You don’t really need much of a methodology at all to write a 5 page website. Limiting specificity is a best practice across all CSS development, and the larger the project the more important that practice is.

    • Stephen Irving says:

      Also, I must add that you are just wrong when you say using multiple level selectors is more efficient. A single class selector will ALWAYS be more efficient and performant than any selector with multiple parts to it.

  3. Kseso says:

    Oh! no. Another evangelist.
    So bad is the abuse of id’s and classes. If they exist why demonize rational use?.

    Preach its use, not its abandonment.

    I think.

    Chris, me too.

    • Did I demonize the rational use of classes? I’m not sure I follow what you’re saying. I’m advising the abandonment of IDs as styling hooks. I use IDs all the time, but for JS hooks and fragment identifiers. But not as much anymore for CSS, if at all.

      Try it some time. You’ll be surprised. On your next project, don’t use any ID selectors in your CSS. You’ll find it so much easier to work with your code, and you’ll never have another specificity problem.

  4. Buckthorn says:

    No blanket statements? Aside from the title itself, these come pretty close. And they’re unsubstantiated as well.

    “LEARNING [emphasis mine] about CSS specificity has the potential to degrade the quality of your code.”

    [Recommending the use of IDs for unique styles]…[]is bad advice and quite silly really.

    “If you’ve created clean CSS…then there’s no reason to use an ID selector”

    “if you know about varying degrees of specificity, then you’re more likely to use those more specific selectors, and use them improperly, as a crutch.”

    If you want to argue the advantages of classes over IDs under specific circumstances, that’s fine. But you’re painting with an awfully broad brush, and are essentially telling people to avoid IDs because it will mess up their sites. I strongly disagree. As with any kind of programming, let the situation and your experience dictate which tool/method you use.

    • Nah. IDs are completely unnecessary, and unintuitive, as styling hooks. I stand by that statement. The only reason I said “no blanket statements” is because sometimes you inherit a project and you simply don’t have time or the budget to restructure the markup, and you have no choice but to use an ID. And you also might have a case where the CMS decides the markup for you, and again, no choice.

      • Buckthorn says:

        OK, so that’s your opinion, and you don’t have to use them. The uses and advantages of IDs have been explained many times elsewhere (they’re also self-evident). I am also a little irked by your implication that developers who consciously decide to use IDs for their own reasons are misled, naive, foolish, or just plain wrong (your response of “nah” doesn’t exactly bolster one’s sense of your respect for what others may think). You seem to be a smart person, but perhaps someday you’ll be a little more careful and respectful, and a little less sweeping in your claims.

        • Buckthorn, I apologize if my informal response led you to believe I didn’t respect your opinion. I do, and I’m glad to hear it. Sometimes I’m in a hurry, so maybe I wrote that quickly and didn’t realize how it might sound.

          I understand that there are ‘uses and advantages’ for IDs, but I believe the drawbacks to using them strongly outweigh those advantages. And keep in mind that I use IDs all the time, just not much anymore for styling hooks.

          So again, I’m sorry for sounding flippant. I have a lot of comments to respond to each day, and I value all of them, but sometimes I write quickly and it may come across the wrong way. In fact, I just finished writing something that promotes the idea that comments are just as important as content.

          So although we disagree on this point, I hope you’ll continue to offer feedback on here or elsewhere. Thanks for your views.

          • Buckthorn says:

            Understood. Thanks for your note. We’ll have to agree to disagree about IDs. But I am also trying to make a broader point. IDs have drawbacks only if they are applied poorly. One could make an even stronger case, perhaps, that using floats for layout could lead to problems, but I would never say “never use floats for layout”, even though I think I have a better method. And that’s because floats can work just fine if used properly. Effectiveness does not necessarily emanate from the tool itself, but rather from the application of that tool.

          • I agree. And that’s an excellent point, and probably that’s why so many people have written articles on CSS specificity — so people can understand it and use it to their advantage.

            But as I said here, I believe if you use classes almost exclusively, specificity can become somewhat irrelevant, because every selector will be on an even playing field, so to speak.

            And in the case of float layouts: If there was an alternative, more effective, and easy to maintain, cross-browser solution, then I would definitely say “Don’t use floats”. :)

  5. I think this article would be better titled as “IDs in CSS are irrelevant”. Specificity is an important concept for front-end web developers to understand. Knowing specificity is knowing why “.class” overrides “span”. Its knowing why “:hover” overrides “:first-child”. Its knowing why “.class1 ~ .class2” overrides “.class2”.

    Specificity isn’t the enemy here. Specificity is simply the set of rules explaining how CSS selectors are applied. Knowing specificity is far from irrelevant – for front-end web developers this stuff is essential.

    • Sorry.. bad typo in my comment there. “:hover” doesn’t override “:first-child” – they are both pseudo-classes. I should have said, specificity is knowing why “:hover” (pseudo-class) overrides “:first-letter” (pseudo-element)

    • Lavabeams says:

      Yeah title is really really misleading.

      • In retrospect, the title might be slightly off, but it’s not that far from the truth. Understanding simple stuff like why element selectors (e.g. “p”) are overridden by classes and IDs is not complicated at all. And understanding why “body article p” overrides “article p” is likewise quite simple.

        But understanding why “#element” overrides “body article p.class span” is quite confusing. And the same would apply to !important styles that can’t be overridden. So the point of the article is that CSS featuers that have high override ability (like IDs and !important, or descendant selectors) are really the only parts of CSS that are difficult to grasp when it comes to specificity.

        Try it: Use classes exclusively in your CSS, and only use other selectors sparingly. You’ll notice that specificity will be a non-issue, just I like I explained in the article.

        But hey, it was a rather exaggerated article title, so I’m going to adjust it slightly to make the title more accurate with regards to what is being discussed. Thank you.

  6. Daniel Flores says:

    I get your point, learning css specificity to try to “master it” seems pointless.

    BUT, learning css specificity to actually know it exists, is crucial, when you have specificity wars, you want to override some bootstrap class, you can’t and you don’t know why.

    When I didn’t know it is a thing, I just assumed, putting another class to the right, would just override the left class.

    Little did I know how wrong I was.

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field and deep URLs are not allowed in the "Website" field. If you use keywords or deep URLs, your comment or URL will be removed. No foul language, please. Thank you for cooperating.

Markdown in use! Use `backticks` for inline code snippets and triple backticks at start and end for code blocks. You can also indent a code block four spaces. And no need to escape HTML, just type it correctly but make sure it's inside code delimeters (backticks or triple backticks).