Now, you know why it's important to structure your code, but to do that effectively, you need to understand a key concept: specificity.
What is specificity?
Let’s look at an example. Say you have a button element with an id
of submit-button
and a class of button
:
HTML
<div id="submit-button" class="button">Click Here!</div>
And in your CSS file, you’ve assigned a different background color to each, as well as the button element:
CSS
#submit-button {
background-color: #15DEA5;
}
.button {
background-color: #DB464B;
}
So, when you look at your button in a browser, what color will it be?
The answer lies in each of the selectors’ specificity. When an element has conflicting rules applied, such as multiple background colors, the browser will apply the rule from the most specific of the selectors.
But just how does a browser determine a selector’s specificity?
The four horsemen of specificity
The browser lumps CSS rules into four categories:
1) Inline styles:
<div style="background-color:#15DEA5;">Click Here!</div>
2) IDs:
<style> #submit-button { background-color: #15DEA5; } </style>
<div id="submit-button">Click Here!</div>
3) Classes, pseudo-classes, attributes:
<style> .button { background-color: #DB464B; } </style>
<div class="button">Click Here!</div>
4) Elements and pseudo-elements:
<style> div { background-color: #DB464B; } </style>
<div>Click Here!</div>
When the browser is deciding which of the conflicting rules to apply, it tallies up the number of categories being implemented by a selector. So our three selectors would be tallied as follows:
#submit-button {...}
:
Inline | ID | Class | Element |
0 | 1 | 0 | 0 |
.button {...}
:
Inline | ID | Class | Element |
0 | 0 | 1 | 0 |
div {...}
:
Inline | ID | Class | Element |
0 | 0 | 0 | 1 |
Once the tallying is done, the browser starts by looking at the scores in the left column, because inline selectors are the most specific. If there’s a selector with a higher score, the browser will apply its style. If there’s a tie, it moves right to the next column and does the same thing.
In the case of our three selectors, the first column is a tie, none have inline styles, so they all score a zero. So, the browser moves right to the ID column, where there is a clear winner: #submit-button
has a score of one, where the others have zero, so the browser will use its rule set for the background color.
Now what if you were to add a second class to the button selector?
HTML & CSS
<style>
.button.submit-button { background-color: #DB464B; }
</style>
<div class="button submit-button">Click Here!</div>
That would change its specificity to:
Inline | ID | Class | Element |
0 | 0 | 2 | 0 |
Although it might seem like the new double class selector of .button.submit-button
would be more specific, it still loses out to #submit-button
. Remember, the browser works from left to right, and since#submit-button
has a higher score in the ID column, the browser stops there. It doesn’t matter if a selector has two classes, or 200, an ID selector will always be more specific than a selector of classes.
But what if you really want to use the color from the class selector? Instead of a second class, you could add the id
to it as well:
HTML & CSS
<style>
#submit-button {background-color: #15DEA5;}
#submit-button.button { background-color: #DB464B;}
</style>
<div id="submit-button" class="button">
Click Here!
</div>
Now you have:
#submit-button {...}
:
Inline | ID | Class | Element |
0 | 1 | 0 | 0 |
#submit-button.button {...}
:
Inline | ID | Class | Element |
0 | 1 | 1 | 0 |
Now there is a tie for the ID column, so the browser moves right to the class column, where .button
wins 1-0, and the browser applies its background color to the button.
As you’ll see in the next chapter, you will often want to override certain attributes with a modifying selector, rather than writing out a ton of specific selectors. This helps make your code more modular and reusable.
As you’ve just seen, ID selectors are difficult and messy to override, and you want to write clean, maintainable code. By sticking primarily with class selectors, you help to ensure that they have lower specificity, making them cleaner and easier to override.
So, what happens if the browser goes through the columns and ends in a tie?
Battle royale: specificity with a tie
Change the #submit-button ID to a class,.submit
and the CSS to match:
HTML & CSS
<style>
.submit {background-color: #15DEA5;}
.button { background-color: #DB464B;}
</style>
<div class="button submit">
Click Here!
</div>
Both .submit and .button have the same score:
.button {...}
:
Inline | ID | Class | Element |
0 | 0 | 1 | 0 |
.submit {...}
:
Inline | ID | Class | Element |
0 | 0 | 1 | 0 |
So, which selector wins out?
In the case of a tie, the browser selects the last selector to have been declared, which is .button
:
So, if you swap them so that.button
is declared last:
<style>
.button { background-color: #DB464B;}
.submit {background-color: #15DEA5;}
</style>
<div class="button submit">
Click Here!
</div>
The browser will use .submit
's background color:
By sticking with classes to create your CSS selectors, you ensure that they have a low but consistent specificity. This makes conflicting rules easier to predict and manage. In the next chapter, you’ll put your new specificity knowledge to use by creating modular structured selectors to style your site.
Try it out for yourself!
Ready to roll up your sleeves and code in this interactive exercise? We have a .btn
class to style our buttons, which features a mint-green background color. As an alternative, we decide to make a class that will turn our button’s background pink, via the hex value #EA526F
. But it doesn’t work! We’ve added it to our second button, but it’s still mint-green…
That means that the original .btn class must have a higher specificity than .btn-pink, right? We need to refactor our CSS so that we can override .btn
’s background color when we apply .btn-pink
.
Calculate the specificities of the button selectors in the CSS file.
Refactor the CSS so that
.btn-pink
overrides .btn’s background color and turns the second button pink.
This can be done by increasing the specificity of .btn-pink
, but in the in interest of maintaining a minimal specificity throughout our code base, we would best be served reducing the specificity of .btn
.
When you're ready, check your work with this CodePen!
Let's recap!
There are four levels of specificity:
Inline styles
IDs
Classes, pseudo-classes, attributes
Elements and pseudo-elements
Your browser applies the most specific elements first.