Selectors and Specificity

From CSS Standards FAQ

Jump to: navigation, search
selector {
	property: value;
}

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(s).

A CSS selector is a way to refer to element(s) in HTML documents. A one or more elements in a document can be referred in several ways. For example, the paragraph element `p` 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>

Here we should note that, when we refer to a `p` element in such a way then in English 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 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 adding up the components that are involved. Which selector overrides another selector is based on this value. We look at the final specificity value from left to right, just like the decimal system. For example, 0100 would be higher then 0010. 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
p { color: #f00; } 0 0 0 0 1 0 0 1 0 1 0,0,0,0,1,0,0,1,0,1
div p { color: #0f0; } 0 0 0 0 1 0 0 2 0 1 0,0,0,0,1,0,0,2,0,1
div p { color: #0ff; } 0 0 0 1 0 0 0 2 0 1 0,0,0,1,0,0,0,2,0,1
div.foo .bar #baz { color: #00f; } 0 0 0 1 0 1 2 1 0 1 0,0,0,1,0,1,2,1,0,1
<p id="foo" style="color: #fff"> 0 0 1 0 0 1 0 1 0 1 0,0,1,0,0,1,0,1,0,1
p { color: #000 !important; } 0 1 0 0 1 0 0 1 0 1 0,1,0,0,1,0,0,1,0,1
* { color: #0f0; } 0 0 0 0 1 0 0 0 1 1 0,0,0,0,1,0,0,0,1,1

In the chart above, the color #000 gets to be applied to the `p` element in the document as a final result. From highest to lowest specificity: (0,1,0,0,1,0,0,1,0,1) > (0,0,1,0,0,1,0,1,0,1) > (0,0,0,1,0,1,2,1,0,1) > (0,0,0,1,0,0,0,2,0,1) > (0,0,0,0,1,0,0,2,0,1) > (0,0,0,0,1,0,0,1,0,1) > (0,0,0,0,1,0,0,0,1,1)

Further Reading

Personal tools