Tutorial

Understanding Specificity in CSS

Published on September 3, 2019
author

Jess Mitchell

Understanding Specificity in CSS

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.

CSS Selector Overview

There are multiple ways to select the elements youโ€™re trying to style in CSS. Letโ€™s start by reviewing all the options.

  • Type Selectors: Select your intended element by using its element type. For example, to select all your <p> tags, use p in your CSS style sheet.
  • Pseudo-Elements: As the name suggests, pseudo-elements are not elements themselves but allow you to select part of your HTML relative to another selector. For example, select the first letter of each paragraph with p::first-letter.
  • Class Selectors: Elements can have multiple classes set on them to be selected in your CSS style sheet. For example, <h1 class='header'> can be selected with .header. Multiple elements can have the same class applied to them.
  • Attribute Selectors: Select elements that have a specific type of attribute applied to them. For example, select inputs that accept numbers only with input[type='number'].
  • Pseudo-Classes: Select elements based on the CSS state theyโ€™re in. For example, style the hovered state of a button with button:hover. Check out these previous tutorials on the :target, :hover and :active pseudo-classes to learn more.
  • ID Selectors: Select a specific element with its unique ID. There can only be one element with each ID, whereas classes can be applied to multiple elements. For example, select <h1 id='mainHeader'> with #mainHeader.
  • Inline Styles: Inline styles are applied to elements directly with the 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;'>

CSS Selectors and Their โ€œWeightsโ€

Each type of selector listed above has a weight. All of these can be divided into four main groups:

  • lowest weight: type and pseudo-element selectors
  • low weight: class, attribute, and pseudo-class selectors
  • medium weight: ID selectors
  • high weight: inline styling

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. ๐Ÿค“

The Problem with Competing Selectors

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. ๐Ÿ‹

Selector Weight Trick

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. โœจ

The Company Analogy for CSS Specificity

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):

  • employees
  • managers
  • directors
  • VPs
  • one CEO (weโ€™ll come back to the CEO in a bit)

Letโ€™s map these roles to our selectors now:

  • employees: type and pseudo-element selectors
  • managers: class, attribute, and pseudo-class selectors
  • directors: ID selectors
  • VPs: inline styling

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.

!important is the CEO

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. ๐Ÿ’ฃ

Please Donโ€™t Use !important

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 !importants 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. ๐Ÿ™ˆ

Universal Selector and Combinators

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.

Learn more about our products

About the authors
Default avatar
Jess Mitchell

author

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.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
ย 
Leave a comment
๏ปฟ

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!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOceanโ€™s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow โ€” whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.