Specificity in Cascading Style Sheets

selector {
    property: value;
}

Cascading Style Sheets (CSS) selector specificity is one of the most important topics in CSS. It is about distinguishing which selector gets to be applied to an element.

A CSS selector is a way to refer to element(s) in HTML documents. One or more elements in a document can be referred in several ways. For example, the p element can simply be referred by its name:

p {
    color: #f00;
}

We can also refer to this element by its location in the document. If we assume that this p element is within a div element then we can refer to it like this:

div p {
    color: #f00;
}

and the corresponding HTML would be:

<div>
    <p>The quick brown fox jumps over the sleepy lazy dog.</p>
</div>

In this case, the style will apply to any p element that is found within div. We should note that, when we refer to p here, it would be saying something like this: "Assign the color #f00 to all p elements that are found inside the div element in the document". In other words, if we have the p element in other locations of the document (places where it is not nested in a div element) then the style we just applied will not work.

We can of course refer to a very specific p element in a document:

<div id="foo">
    <div class="bar">
        <p id="baz">The quick brown fox jumps over the sleepy lazy dog.</p>
    </div>
</div>

by providing more information:

div#foo .bar p#baz {
    color: #f00;
}

In the style above, we are referring to a very specific p element in the document since it is telling the user-agent to "locate the p element with the identifier 'baz' that is within an element that has a class assignment of 'bar' which is also within another element div with the identifier 'foo'."

Since identifiers are unique to per HTML document, then we know that there should only be a single instance of 'baz'. This actually gives us a lot of information about the p element in the document. Simply because we can refer to the p element this way instead:

#baz {
    color: #f00;
}

For clarity, and also for specificity reasons (we will come to this shortly) we could use this:

p#baz {
    color: #f00;
}

instead. So, depending which p element(s) we want to target, we can be as specific as we like. Therefore, the more specific element we target then that element will take on the styles of that selector. To build on the examples we used above, observe the following in a document:

<div>
    <p>The quick brown fox jumps over the sleepy lazy dog.</p>
</div>

p {
    color: #f00;
}

div p {
    color: #0f0;
}

What happens here is that, the color #f00 gets to be applied to the p element, however since there is a rule that says "Hey look, I have a selector here thats targeting a p element inside a div element", it is more specific then the generic selector. Hence, the color #0f0 gets to be applied to that p element in the document instead. Easy eh?

In the case of applying the !important rule to a property value, it is telling the user-agent "Hey I'm the author of this document, and I say what goes on around here. Regardless of any similar styles, I want to make sure that this style overrides all other styles mentioned anywhere else in the document". Then in this case:

<div>
    <p>The quick brown fox jumps over the sleepy lazy dog.</p>
</div>

p {
    color: #f00 !important;
}

div p {
    color: #0f0;
}

the color #f00 gets applied to p element even though it seems like div p is more specific. Try to avoid the usage of !important unless you really have to take control of the applied styles. In most cases increasing the specificity level can give you the control you need.

The examples above are declaring styles in a way that you would see in external stylesheets or internally in an HTML document. What happens with the user-agent is that there are 4 possible ways CSS gets to be applied.

  1. Browser/user default
  2. External
  3. Internal (inside the <head> tag)
  4. Inline (inside an HTML element)

So, the user-agent (browser) will apply its default styles to a document and then apply the other possibilities. If a document has an external stylesheet it will be applied (and overrides) on top of the defaults. Then, if the document has an internal stylesheet that will be applied on top of the external stylesheet. And finally the inline styles embedded within the HTML elements.

Now then, if we have an external style like:

div p {
    color: #f00;
}

and an internal style like:

<style type="text/css">
    p {
        color: #0f0;
    }
</style>

the internal style with color #0f0 takes over the external style.

In the case of inline styles:

<p style="color:#00f">The quick brown fox jumps over the sleepy lazy dog.</p>

they have the highest selector specificity. However, as we mentioned earlier the !important rule gives the control back to the author and allows them to apply the property and its value over the inline style, For example:

<p style="color:#00f">The quick brown fox jumps over the sleepy lazy dog.</p>

p {
    color: #f00 !important;
}

the color #f00 gets to be applied to the p element.

The final specificity of a selector is calculated by combining the components that are involved. Which selector overrides another selector is based on this value. We look at the specificity value from left to right. For example, 0,1,0,0 would be higher then 0,0,1,0. And 0,1,0,0 would still be higher then 0,0,13,0. Since in most cases the user-agent style is present by default, it will always have a value of 1. And the 'user' style refers to the styles that are explicitly provided by the user, which has the power to override any style. Universal selector is a style that cascades down to all elements that are nested. Inherited styles have no impact on specificity.

To simplify this, we essentially don't need to worry about universal, inherited and user-agent default styles and occasionally not about the user specific styles since it is beyond the control of the document's author.

Specifity example chart
Selector user override inline internal external # of identifiers # of classes # of elements universal user-agent defaults Specificity

In this chart the color #000 gets to be applied to the p element in the document. From highest to lowest specificity:

  1. (0,1,0,0,1,0,0,1,0,1)
  2. (0,0,1,0,0,1,0,1,0,1)
  3. (0,0,0,1,0,1,2,1,0,1)
  4. (0,0,0,1,0,0,0,2,0,1)
  5. (0,0,0,0,1,0,0,2,0,1)
  6. (0,0,0,0,1,0,0,1,0,1)
  7. (0,0,0,0,1,0,0,0,1,1)
p { color: #f00; }00001001010,0,0,0,1,0,0,1,0,1
div p { color: #0f0; }00001002010,0,0,0,1,0,0,2,0,1
div p { color: #0ff; }00010002010,0,0,1,0,0,0,2,0,1
div.foo .bar #baz { color: #00f; }00010121010,0,0,1,0,1,2,1,0,1
<p id="foo" style="color: #fff">00100101010,0,1,0,0,1,0,1,0,1
p { color: #000 !important; }01001001010,1,0,0,1,0,0,1,0,1
* { color: #ff0; }00001000110,0,0,0,1,0,0,0,1,1

References and Resources

Published

Interactions

2 interactions

bruce’s photobruce replied on

This was very good and useful.

You should extend this, perhaps show off some of CSS3's features such as input[type=text], etc.