CSS Specificity
Tags: beginners, css
Published: 2019-10-30 14:09:01

---
title: CSS Specificity
published: true
description: An Introduction to CSS Specificity
tags: beginners, css
series: FrontEnd Development Zero to Hero
---

CSS specificity is _one of the mechanism_ used by the browser to resolve conflicts in your CSS rules. Now you might be thinking: conflict? What conflict?

Given the code snippet below, which particular CSS rule do you think will get applied to the HTML paragraph?

```html
<div>
 <p id="paragraph">Hello world, welcome to frontend zero to hero</p>
</div>
```
```css
p {
  font-size: 120%; /* option one */
}

div p {
  font-size: 0.5em; /* option two */
}

#paragraph {
  font-size: 10px; /* option three */
}
```

Taking a closer look, you'll notice that we are trying to change the `font-size` of the paragraph with three different rules in our CSS. That's the conflict I was talking about. But which rule will the browser use? Take a guess.

_Option three_ will win. Why _option three_? When you give such rules, the browser will use one of its a mechanism in resolving conflicts in CSS rules — _specificity_. In this case, the browser will use the rule declared with the _id selector_ to style the paragraph. How could this be? To answer this question, let's find out how the browser calculates a selector specificity.


###__CALCULATING A SELECTOR SPECIFICITY__
From the [CSS Specification](https://www.w3.org/TR/2011/REC-CSS2-20110607/cascade.html#specificity):

> A selector's specificity is calculated as follows:
* count 1, if the declaration is from, is a 'style' attribute rather than a rule with a selector, 0
otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules.
These rules have no selectors, so a=1, b=0, c=0, and d=0.)
* count the number of ID attributes in the selector (= b)
* count the number of other attributes and pseudo-classes in the selector (= c)
* count the number of element names and pseudo-elements in the selector (= d)

At first glance this might be confusing, let's explain each step of the algorithm.

> count 1 if the declaration is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules.

__This translates to__: When you apply some styling to an HTML Element using the `style` attribute it will have a value of `1` and all property declaration in this `style` attribute will be used by the browser even if you declare the same set of properties with other selectors (`id`,`class` or `type selectors`).

Let's use our previous example with a slight modification. Save the HTML code in a file with the `.html` extension and the CSS with a `.css` extension, and make sure the CSS is linked with the HTML (_if you don't know how to do this, please check the previous article [CSS units](https://dev.to/ziizium/css-units-2bh1)_)

```html
<div>
  <p id="paragraph" style="font-size: 20px">Lorem ipsum dolor sit
amet, consectetur adipisicing elit,.</p>
</div>
```
```css
p {
  font-size: 120%; /* option one */
}

div p {
  font-size: 0.5em; /* option two */
}

#paragraph {
  font-size: 10px; /* option three */
}
```

Load the file in your browser, Use "Inspect Element" on the paragraph, you will get an output similar to the image below:

![Specificity in CSS](https://thepracticaldev.s3.amazonaws.com/i/2j2g8sn6o3d7nil6h3mg.PNG)

From the image above, if we observe the __Computed__ tab, we'll see that the browser is using `20px` as the `font-size`.

This clearly indicates that property declarations in the `style` attribute takes precedence over the same set of property declarations declared with an `id`, `classes`, `pseudo-selectors` and plain `tag selectors`. That's why it's given a value of `1` and the specification assign it the letter `a`.

<hr>

> count the number of ID attributes in the selector (= b)

After the `style` attribute, property declaration in an `id` attribute takes precedence over the same set of property declarations in other attributes and elements as demonstrated at the beginning of this post.

`id's` are given the number `0` and assigned the letter `b` in the specification.

<hr>

> count the number of other attributes and pseudo-classes in the selector (= c)

This tells us that `classes`, `attribute selectors` and `pseudo-class` takes precedence over `type selectors` and `pseudo-elements`. Let's take an example.

```html
<div>
  <p class="paragraph">Lorem ipsum dolor sit amet, et dolore magna aliqua.</p>
</div>
```
```css
/* property declaration with one tag (div) and a pseudo-selector (:first-child)*/
div:first-child {
  font-size: 50px;
}
.paragraph {
  font-size: 120px;
}
```

Load the file in your browser and use "Inspect Element" in the paragraph. You will realize the browser opted to apply the property declared with the `class`. They are assigned the number `0` and the letter `c` in the specification.

![Specificity in CSS](https://thepracticaldev.s3.amazonaws.com/i/twv0qtch55c1j5l0xakh.PNG)

<hr>

> count the number of element names and pseudo-elements in the selector (=d)

Pseudo-elements and tag selectors are last in the chain they are assigned the number `0` and letter `d` in the specification.

In summary:
* `style` : assigned number `1` and letter `a`
* `id` : assigned number `0` and letter `b`
* `classes`, `attribute selectors`, `pseudo-classes`: assigned number `0` and letter `c`
* `type selectors` and `pseudo-elements`: assigned the number and letter `d`

The default number assigned to this selectors in the specification can be summed up as: `1`, `0`, `0`, `0`

Now you might think: will the numbers assigned to these selectors ever change? Yes, except that of the `style` attribute, it will always be `1` because <u>HTML does not allow duplicate attributes</u> applied to an element and if you make such a mistake, the browser will use the first one and gladly ignore the rest.

Take the code sample below, multiple `font-size` declarations are applied to the paragraph but only the first is applied by the browser.

```html
<div>
  <p style="font-size: 50px;" style="font-size: 100px;" style="font-size: 200px;">
Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</div>

```
![A paragraph in HTML with 50px font size applied](https://thepracticaldev.s3.amazonaws.com/i/kby5rh8er6d2pr3sapum.PNG)

And if you use `viewsource` on your code, you'll see the error highlighted in red.

![Duplicate attribute in Viewsource](https://thepracticaldev.s3.amazonaws.com/i/xokf6v65p3fq3e6uh87y.PNG)

For the remaining selectors, <u>their number increase based on the number of times they are applied to an element</u>, but _the selector higher in ranking will always take precedence_ irrespective of the number of times you apply any selector that's is lower in precedence. Given the code snippet below:

```html
<div>
  <p id="lot-of-ps" class="p1 p2 p3 p4">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, aliqua.</p>
</div>
```
```css
#lot-of-ps {
  font-size: 10px;
}

.p1.p2.p3.p4 {
  font-size: 40px;
}
```

In this case, `font-size` declared with the `id` selector will win because it has a higher specificity than all the classes combined. Which gives the following number `0`, `1`, `4`, `0` 

* `0` - we did not use a `style` attribute, so it gets a zero
* `1` - we had one `id` selector, hence the number one
* `4` - we applied four `class selectors`
* `0` - we did not use any `pseudo-element` selector, so it gets a zero  

![CSS Specificity](https://thepracticaldev.s3.amazonaws.com/i/2j093vdtiu53v0c8n8jl.PNG)

Now, what happens if we have no `id` selector? Take the code snippet below, which CSS selector wins?

```html
  <div>
    <p class="p1 p2 p3 p4">Lorem ipsum dolor sit amet, ut labore et dolore aliqua.</p>
 </div>
```
```css
.p1.p2.p3.p4 {
  font-size: 40px;
}

div p.p1 {
  font-size: 100px;
}
```

The first CSS selector will win because it has a specificity value of `0`, `0`, `4`,`0`:
* `0` - no `style` attribute selector
* `0` - no `id` selector
* `4` - four `class` selectors
* `0` - we used two `tag selector` `div` and `p`


###__TOOLS FOR UNDERSTANDING CSS SPECIFICITY__

[Keegan Street](https://twitter.com/kstre) Created a tool [CSS Specificity Calculator]( https://specificity.keegan.st/), it automatically shows the Specificity of your declaration when you type (or paste) in your CSS declaration. 

[Andy Clarke](https://stuffandnonsense.co.uk/) has a [poster illustrating CSS specificity](https://stuffandnonsense.co.uk/archives/css_specificity_wars.html) using characters from Star Wars.

[Estelle Weyl](http://www.standardista.com/) co-author of _[CSS The Definitive Guide Visual Presentation for the Web  Fourth Edition](https://www.amazon.com/CSS-Definitive-Guide-Visual-Presentation/dp/1449393195/)_ created [specifishity](
https://specifishity.com/).

Now, what happens when the selectors have the same specificity?

```css
/*0012*/
div p.p1 {
  font-size: 100px;
  color: red;
}

/*0012*/
div p.p1 {
  font-size: 200px;
  color: orange;
}
```

Which selector will the browser use? That's when the 'C' in CSS comes into play, _The Cascade_.

That is next.