Relationship Between !Important and CSS Specificity

Relationship between !important and CSS specificity

Specificity in CSS only concerns selectors, not their associated declarations. !important applies to a declaration, so it alone plays no role in specificity.

However, !important influences the cascade, which is the overall calculation of styles for a certain element when more than one of the same property declaration applies to it. Or, as Christopher Altman succinctly describes:

  1. !important is a spades card. It trumps all specificity points.

But not only that: because it influences the cascade overall, if you have more than one !important selector with a rule containing an !important declaration matching the same element then selector specificity will continue to apply. Again, this is simply due to having more than one rule applying to the same element.

In other words, for two rules with unequal selectors in the same stylesheet (e.g. same user stylesheet, same internal author stylesheet, or same external author stylesheet), the rules with the most specific selector apply. If there are any !important styles, the one in the rule with the most specific selector wins. Finally, since you can only have something that's either important or not, that's quite as far as you can go in influencing the cascade.

Here's an illustration of the various uses of !important and how they're applied:

  • The !important declaration always overrides the one without it (except in IE6 and older):

    /* In a <style> element */
    #id {
    color: red !important;
    color: blue;
    }
  • If there is more than one !important declaration in a rule with the same level of specificity, the later-declared one wins:

    /* In a <style> element */
    #id {
    color: red !important;
    color: blue !important;
    }
  • If you declare the same rule and the same property in two different places, !important follows the cascading order if both declarations are important:

    /* In an externally-linked stylesheet */
    #id {
    color: red !important;
    }

    /* In a <style> element appearing after the external stylesheet */
    #id {
    color: blue !important; /* This one wins */
    }
  • For the following HTML:

    <span id="id" class="class">Text</span>

    If you have two different rules and one !important:

    #id {
    color: red;
    }

    .class {
    color: blue !important;
    }

    That !important always wins.

    But when you have more than one !important:

    #id {
    color: red !important;
    }

    .class {
    color: blue !important;
    }

    The #id rule has a more specific selector, so that one wins.

CSS specificity and !important

Styles for a directly targeted element will always take precedence over inherited styles, regardless of the specificity of the inherited rule.

-- Specificity: Directly targeted elements vs. inherited styles


Note: the addition of the new contrived ruleset in Demo:

div.outer.outer.outer>div.inner1>div.inner2.inner2>aside.inner3 {
color: blue !important
}

It has an incredibly ridiculously unnecessarily huge specificity score of 0,0,7,4 and !important as well. CSS reads from right to left:

  1. Find an <aside> tag with the class of .inner3
  2. It must have a parent <div> that has the class of .inner2.
  3. Also that <div class="inner2">must have a parent <div> with a class of .inner1.
  4. And it's imperative that <div class="inner1"> have a parent <div> with the class of .outer.

All of these specific rules of the selector must be met just so a deeply nested <aside> tag gets its style. Any descendant elements of .inner3 will inherit color: blue property and value, but it is easily overridden by the likes of i.inner2 with color:red.

   <div class="inner3">
<p>This deeply nested text has <i class='inner2'>crazy specificity but this text is red.</i>
...
</p>
</div>

Note: the new ruleset at the bottom of CSS box:

  div {
color: black !important
}

Now this selector is specific to all divs so here is how !important has just been assigned a selector with a far reaching scope. This is probably more like the behavior you were expecting.


BTW, you probably noticed the duplicate classes:

  .outer.outer.outer

That is called selector chaining which will increase a selector's specificity score. See Online Specificity Calculator.


Demo


div.outer.outer.outer>div.inner1>div.inner2.inner2>aside.inner3 {  color: blue !important}
.outer .inner1 { color: green !important;}
.outer .inner1 .inner2 { color: red;}
div { color:black !important;}
<head>  <link href="css/style.css" rel="stylesheet">  <link href="css/style1.css" rel="stylesheet"></head>
<body> <div class="outer"> <div class="inner1"> This text will be green... <div class="inner2"> <p>Voluptate labore cupidatat an enim quamquam ut anim malis, varias id sed veniam quibusdam, singulis aliqua ut singulis domesticarum, id aliqua illum o officia, et ab domesticarum, irure e excepteur o eram nam appellat coniunctione do commodo.. </p>
<aside class='inner3'> <p>This deeply nested text has <i class='inner1'>crazy specificity</i>, yet it only applies to it and its descendants with no specific <b class='inner2'>`color` property</b>.</p> </aside> </div> ...and this text will be green as well. </div> </div>

Why do I have to use the !important in this case?

Be more specific with your css and remove all your !importants:

.parent div.child {
width: 50%;
height: 50px;
}

should work just fine

Understanding specificity: achieving desired selector outcomes without using !important

A class has a specificity of 10. An element has a specificity of 1.

Therefore, in the first instance:

  • the .main li a selector has a specificity of 12.
  • the .active a selector has a specificity of 11

Because they both target the same element, and the former has a higher specificity, the latter loses the battle to style the element.

In the second instance:

  • the .primary p selector has a specificity of 11.
  • the .copyright selector has a specificity of 10.

Again, because they both target the same element, and the former has a higher specificity, the latter loses the battle to style the element.

The !important annotation trumps all specificity. Hence, with that applied, .active a and .copyright re-take the elements.

If you want to remove !important, which would be the right thing to do as it's not necessary here, you can instead boost the specificity of the selectors.

An ID has a specificity of 100. So that can quickly move a selector up in priority.

Here are some examples:

.main li a      { color: #7ab2c1; }  /* previous winner; specificity 12 */.main .active a { color: #ff0000; }  /* added class selector; specificity now 21 */.primary p      { font-size: 12px; } /* previous winner; specificity 11 */#copyright      { font-size: 8px;} /* switched to ID selector; specificity now 100 */
<nav class="main">  <ul class="group">    <li class="active"><a href="#">Home</a></li>    <li><a href="#">About</a></li>    <li><a href="#">Contact</a></li>  </ul></nav><footer class="primary">  <p><a href="#">Sign up</a> for our newsletter, it's a racket!</p>  <p id="copyright">Copyright © Sven's Snowshoe Emporium.                    All Rights Reserved.</p></footer>

More important than !important (a higher level !important)?

No, there is no keyword or other way to make a declaration more important than !important. There is no known activity to change this.

In general, it is possible to override a declaration that has !important by using a rule that also has it and that has higher specificity. However, a declaration in a style attribute has, by definition, higher specificity than any other author declaration. The only way to defeat it is in CSS is to use a user style sheet with !important.

There are non-CSS solutions, but they are rather obvious, such as using JavaScript to simply remove or modify the style attribute.

What are the implications of using !important in CSS?

Yes, I'd say your example of using !important is bad practice, and it's very likely it would cause undesired effects further down the line. That doesn't mean it's never okay to use though.

What's wrong with !important:

Specificity is one of the main forces at work when the browser decides how CSS affects the page. The more specific a selector is, the more importance is added to it. This usually coincides with how often the selected element occurs. For example:

button { 
color: black;
}
button.highlight {
color: blue;
font-size: 1.5em;
}
button#buyNow {
color: green;
font-size: 2em;
}

On this page, all buttons are black. Except the buttons with the class "highlight", which are blue. Except that one unique button with the ID "buyNow", which is green. The importance of the entire rule (both the color and font-size in this case) is managed by the specificity of the selector.

!important, however, is added at a property level, not a selector level. If, for instance, we used this rule:

button.highlight {
color: blue !important;
font-size: 1.5em;
}

then the color property would have a higher importance than the font-size. In fact, the color is more important than the color in the button#buyNow selector, as opposed to the font-size (which is still governed by the regular ID vs class specificity).

An element <button class="highlight" id="buyNow"> would have a font-size of 2em, but a color blue.

This means two things:

  1. The selector does not accurately convey the importance of all the rules inside it
  2. The only way to override the color blue is to use another !important declaration, for example in the button#buyNow selector.

This not only makes your stylesheets a lot harder to maintain and debug, it starts a snowball effect. One !important leads to another to override it, to yet another to override that, et cetera. It almost never stays with just one. Even though one !important can be a useful short-term solution, it will come back to bite you in the ass in the long run.

When is it okay to use:

  • Overriding styles in a user stylesheet.

This is what !important was invented for in the first place: to give the user a means to override website styles. It's used a lot by accessibility tools like screen readers, ad blockers, and more.

  • Overriding 3rd party code & inline styles.

Generally I'd say this is a case of code smell, but sometimes you just have no option. As a developer, you should aim to have as much control over your code as possible, but there are cases when your hands are tied and you just have to work with whatever is present. Use !important sparingly.

  • Utility classes

Many libraries and frameworks come with utility classes like .hidden, .error, or .clearfix. They serve a single purpose, and often apply very few, but very important, rules. (display: none for a .hidden class, for example). These should override whatever other styles are currently on the element, and definitely warrant an !important if you ask me.

Conclusion

Using the !important declaration is often considered bad practice because it has side effects that mess with one of CSS's core mechanisms: specificity. In many cases, using it could indicate poor CSS architecture.

There are cases in which it's tolerable or even preferred, but make sure you double check that one of those cases actually applies to your situation before using it.

!important isn't working : style inherits from specific selector instead

If you inspect the page, you can see that the style font-size: 50pt !important; is being applied to the h2, just like it says in the stylesheet. But the h2 has no text, it only contains a span. The span can inherit text styles from its parent, but these inherited styles are not the highest specificity for the child elements that inherit them, even though you used !important.



Related Topics



Leave a reply



Submit