How CSS Works  Behind The Scene - Cascade & Specificity

How CSS Works Behind The Scene - Cascade & Specificity

Featured on Hashnode

You must have been wondering what cascade means in CSS, cascade is a process of combining different stylesheets and resolving conflicts between different CSS rules and declarations, when more than one rule applies to a certain element.

CSS can come from different sources or files, examples of such sources are;

  1. User Declaration: examples of such declarations are when users make any changes in the browsers settings e.g. changing the default font size of a browser. There are the most important declarations, and are automatically marked with the !important keyword.

  2. Author Declaration: these CSS scripts are usually written by developers. There are the second most important declarations marked with the !important keyword.

  3. Browser Declaration: These declarations are the default styles a browser adds to a website when no CSS declaration is made for a particular HTML element, for instance when an anchor tag isn’t styled by a developer, it is usually underlined and with a blue color. That’s the user agent declaration because it is set by the browser. There are the least important declarations.

How Does the Cascade Resolve Conflict When More Than One Rule Applies?

Now that we are aware of the different sources that can affect our CSS styling, let’s dive into how the cascade can resolve conflict when more than one CSS rule applies to just one HTML element.

So how does it resolve such conflicts? Well! What it does is to look at:

  1. The importance

  2. Selector Specificity

  3. Source Order

1. Importance

In order to determine which CSS style takes precedence;

Firstly, the cascade starts by giving the conflicting declarations different importance’ based on where they’re declared (i.e. their source). As we’ve seen above, the user declarations are the most important declarations while the author declarations are the second most important declarations and the browser as the least most important declarations. This is why when a user changes the font-size of the browser, it overrides the author’s declaration font-size.

The !important keyword when declared by the author himself only works when they are two conflicting rules in the author declaration. It cannot override the user declaration. Let’s look at an example here;

1.PNG

Result:

1 - result.PNG

Note: Other rules were added to change the text color and padding of the button, it was intentionally not added to the above code snippet as it is not focus but just the background-color.

As you can see in the above example, there are two conflicting rules for background-color and the one with the !important keyword took precedence over the second one.

2. Selector Specificity

A lot of times, we would have a bunch of conflicting rules in our author declaration/stylesheet without any !important keyword. Now, what happens in this case?

What the cascade does if this is the case is to calculate and compare the specificities of the declared selectors. This is how it works;

  • Inline styles have the highest specificity
  • IDs have the second highest specificity
  • Classes, pseudo-classes and attribute selectors, the third highest specificity
  • Element and pseudo-element selectors, the least specificity

Let’s take a look at another example where there are two conflicting rules with one of them having a background-color: blue;, and the other with background-color: green;. With these two conflicting rules, how would the browser know which one to implement? Well! We will see how the browser selects which of the two rules to be implemented in the example below:

2.PNG

Result:

2 - result.PNG

Now, you’re probably wondering what the numbers in the comments mean and how we would use these numbers to find out which of the selectors applies. We start to look at numbers from left to right starting with the most specific category, the inline styles, if there’s a selector with one or more it wins against all the other selectors.

Well! In this case both selectors have no inline styles but they do have internal styles which makes them a tie. Now, let’s move to the IDs, we see that the second selector has one ID while the first selector has none which makes it a zero, so the one with a zero is out of the game because it is less specific than the second selector - the one with an ID.

Since the second selector has one ID and the other one has a zero ID, the second selector therefore becomes our winner. It is the most specific selector among the two selectors, so it will give our button a green background.

In some cases, the ID category can have a tie, i.e. they either have no IDs or both have the same numbers of IDs. In this case, the cascade would then move to the class category to check for its winner, if there’s still no winner here, then it moves to the element category until it finds a selector with the highest specificity among the conflicting selectors.

The value of the winning declaration is called the cascaded value, because it’s from the cascade.

3. Source Order

At this point, I know you must be worried that what if the cascade doesn’t find a winner in all the specificity categories, what then happens? Will none of the conflicting rule work?

Well! This is where the source order comes in. The last declaration in the code between both selectors will override all other declarations and will be applied.

Conclusion

This is the reason why you shouldn’t link any CSS libraries such as bootstrap after your custom CSS, instead have your CSS libraries linked first at the top before your custom CSS as you might want to override some of the library’s CSS rules in your own custom CSS.