Specificity in CSS refers to the how browsers determine the importance, relevance, and โseniorityโ of CSS styles. Here weโll look at all the CSS styling types and use the company analogy to understand how competing styles get resolved.
There are multiple ways to select the elements youโre trying to style in CSS. Letโs start by reviewing all the options.
<p>
tags, use p
in your CSS style sheet.p::first-letter
.<h1 class='header'>
can be selected with .header
. Multiple elements can have the same class applied to them.input[type='number']
.button:hover
. Check out these previous tutorials on the :target, :hover and :active pseudo-classes to learn more.<h1 id='mainHeader'>
with #mainHeader
.style
attribute so you donโt actually use any CSS selectors. For example, you can make your header font color blue directly with <h1 style='color: blue;'>
Each type of selector listed above has a weight. All of these can be divided into four main groups:
If styles of differing weights are applied to the same element, the styling with the higher weight will be applied. If styles of even weights are applied, the styles that come last (nearest to the end of your style sheet) will be applied. This is due to the โcascadingโ effect of CSS (Cascading Style Sheets).
For any element being styled, the last applicable block of styling with the highest weight will be applied to your element. Inline styling will trump CSS selector styling, though. ๐
When two selectors of the same weight are applied to an element, it counts as 2x the weight. So, for example, an element selected with two classes will have a higher weight than just one in your CSS.
.gator.cayman { // two classes
color: purple;
}
.gator { // one class
color: purple;
}
The main issue most of us web developers will face at some point is having multiple styles that interfere with each other. If you use a CSS framework, like Material UI, you may be trying to override some default styles. Alternately, you could have an old (and disorganized ๐) styles.css
file where you keep having to increase specificity because itโs not clear why your styles arenโt getting applied as expected.
Like anything in web development, understanding your tools well will lead to them being used more accurately. Letโs take a look at how different combinations of selectors impact specificity and some tricks to get your styles applied as intended. ๐ค
Understanding that different selectors have different weights is crucial for getting your CSS organized. But what if itโs not clear what has a higher weight?
Letโs say we have a paragraph that has two completing blocks of CSS: one with three matching classes and another block with a type attribute and two matching classes.
For example, letโs take this input with three classes and a number
type attribute applied to it.
<input type='number' class='gator cayman reptile'>
If we apply these competing selectors (three matching classes vs. two matching classes and an attribute), which one will get applied?
.gator.cayman.reptile {
color: purple;
}
[type='number'].gator.cayman {
color: green;
}
In this case, the โweightโ of both blocks is completely even. Attribute selectors and class selectors have the same weight and each block has three of them in total. Since theyโre even, we rely on the cascading effect of CSS. The last one gets applied and the input font color will be green.๐
This gets a little more complicated when you have selectors of different weights getting mixed, though.
Letโs update our input to have an ID, which has a higher weight than classes and attributes.
<input
type='number'
id='gatorInput'
class='gator cayman reptile'>
If we have competing styles again and use the ID for one and the classes/attribute for the other, which will get applied?
#gatorInput {
color: purple;
}
[type='number'].gator.cayman.reptile {
color: green;
}
In the first block, only one ID is being used to apply the styling. In the second block there are three classes and an attribute selector, and it comes last. Even though there are more selectors in the second block, the ID selector has a higher weight and the text will be purple! ๐ฅ
Selectors with a higher weight will always trump those with a smaller weight, even if there are multiple selectors of a lower weight. ๐
One trick (okay, hack ๐ฉ) in CSS when you just need a little more weight is repeating a class in the same block of CSS.
input.gator.gator {
color: purple;
}
input.gator {
color: green;
}
It might surprise you to know that the first block has a weight of two classes and the second block has a weight of one class, even though the first just repeats the class .gator
. Because two classes has a higher weight than one, the input text will be purple! ๐
You shouldnโt ever need to use this trick in production-level code because itโs an indicator that you have styles of very similar weights competing. Ideally, you should resolve those styles to be more clearly defined. However, this is a nice tool in your CSS toolbox when youโre in a โjust make it workโ mode. โจ
Specificity can sometimes feeling counter-intuitive, especially if youโre stuck in a downward spiral of adding more and more selectors to your CSS. One way I find helpful to think about specificity is by thinking of a company with clear seniority levels.
Here are our companyโs roles in order of seniority (low to high):
Letโs map these roles to our selectors now:
Letโs look at a new example. In this case we have a paragraph with two classes and an ID.
<p id='gatorParagraph' class='gator reptile'>
blah blah blah
</p>
#gatorParagraph {
color: purple;
}
p.gator.reptile {
color: green;
}
We have one block that uses an ID only and another block that uses an element type (<p>
) and two classes. At first glance it could be hard to know which one will get applied.
If we use our company analogy, we have one director saying to make the text purple. On the other hand, we have an employee and two managers saying to make it green. Because the director has the highest seniority, she can trump the employee and managersโ opinions. So the text has to be purple!
(No comment on whether this is how decisions should be made at the company ๐).
Consider each weight level a way of escalating the decision of which styles to apply. If it canโt be decided by the selectors on the same level, escalating it will give the decision to the selector of higher seniority.
As a general rule, itโs best to write CSS that is specific enough youโre not going to have to find ways to keep escalating it. Be aware that once you introduce a new level of seniority, like an ID, you could be overriding other styles unintentionally too.
So far we havenโt discussed who our companyโs CEO is in this analogy for CSS specificity. Whatโs higher than inline styling? The !important
rule!
Using our same example as before, letโs add !important
to the block that previously had a lower weight/seniority.
#gatorParagraph {
color: purple;
}
p.gator.reptile {
color: green !important;
}
Adding !important
will always escalate the seniority to be the highest possible level. With our company analogy, we now have a director vs. an employee, two managers, and the CEO. As soon as the CEO is introduced, she can trump anything else being suggested. ๐ฃ
The !important
rule is a slippery slope and seeing it in your CSS styles is generally a red flag that the specificity needs to be reorganized. It is rare that there will be an element that can only be styled by nuking the rest of your CSS rules that would otherwise be applied.
Once you introduce !important
, it often leads to being overused like in the example below. The !important
s cancel each other out and youโre back to having to understand the weight and cascading effect of each block.
#gatorParagraph {
color: purple !important;
}
p.gator.reptile {
color: green !important;
}
Instead of using the !important
rule, try opening your dev tools in the browser to get a better understanding of which styles are interfering with your new ones.
Once you know what styles are causing you trouble, you can either add additional selectors of the same level of weight, or update your markup to use different selectors. ๐
Using !important will often inevitably lead to having competing CSS styles that both use !important. ๐
The universal selector (*
) and combinators do not impact the weight of your selectors. Combinators include child selectors (>
), general sibling selectors (~
), and adjacent sibling selectors (+
).
For example, if we have a paragraph with two spans, using a child combinator will not increase the specificity over not using it:
<p id='gatorParagraph'>
<span class='reptile'>eggs</span>
<span class='reptile'>nest</span>
</p>
#gatorParagraph > .reptile {
color: purple;
}
#gatorParagraph .reptile{
color: green;
}
These blocks of CSS has the same specificity โ the child combinator makes no difference โ so the text will be green.
One of the best visuals for understanding CSS specificity is called specifishity, by Estelle Weyl. Check it out! ๐ค
Also, if youโre not keen on adding up specificity weights yourself, thereโs a specificity calculator that will do the math for you. ๐ฅณ
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the โreport an issueโ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!