Apart from wrongly spelled identifier names in CSS, the next most probable reason why our CSS style is not being applied is because of CSS specificity. It is the rule the determines which style gets applied when there is a conflict. The workaround for this is usually to slap !important on whichever style we want to be applied but there are better ways to go about it.
Although some libraries or frameworks used during development makes it almost impossible to escape the use of !important to override styles, it is possible to write CSS without making use of it. Learning about CSS specificity helps to understand which rules get picked and why.
Selector Hierarchy
In CSS, there are a bunch of selectors e.g ID selectors, Class selectors, attribute selectors, etc. The following lists selectors in order of specificity, from high to low:
- ID selectors
- Class selectors, attribute selectors, and pseudo-classes
- Elements and pseudo-elements
It is important to note that inline styles always override styles in external stylesheets and should be considered to top this hierarchy due to having the highest specificity.
Calculating specificity
The specificity of a CSS rule can be calculated but before we get to that, let us touch on a few points to help us navigate what comes first and therefore gets applied. We've already established that when two CSS rules are conflicting, the one with the greater specificity is applied. Other points to note are:
- When two rules have equal specificity, the latest rule counts. This implies that the last rule in our stylesheet is the one that will count.
- Inherited rules and the universal selector have no specificity. This implies that they can easily be overridden.
- A more specific or targeted selector is likely to have higher specificity for example a rule targeted at a child element using
.parent .child{ }
where .parent and .child are element class names - ID selectors have a higher specificity than class selectors.
Class selectors have a higher specificity than the element selectors
Specificity is based on the form of the selector. Take this piece of CSS code for example :
The first rule is treated as an attribute selector even if it is targeting an ID, this implies that the second rule has more specificity and the text color will be red.
Now on to calculating specificity
If we want to calculate the specificity of our rules then we can do the following:
- Assume a specificity of 0.
- Add 1000 for a style attribute i.e an inline style.
- Add 100 for each ID.
- Add 10 for each class, pseudo-class, or attribute.
- Add 1 for every element or pseudo-element.
Let's see a few examples
The specificity of the rule above is 121 because we have an ID selector which equates to a 100, two class selectors and an element selector
The specificity of the above rule is 11 because we have one class selector and an element selector.
In the event of conflicting styles, our calculated specificity tells us which rule gets applied.
On a closing note, if ever in doubt, then, make use of the ID selector to increase specificity. Be as specific with your rules as possible and always target elements if need be instead of depending on inheritance. Lastly, as important as !important is, it should be avoided. Happy coding!