What made CSS finally stop being so frustrating to me was sitting down to really learn how the language works (along with learning how to debug it effectively). Much like the order of operations in Math, order and specificity are essential to understanding and writing stylesheets.
This guide is designed as more of a primer than a comprehensive lesson. My goal is an approachable introduction for CSS beginners.
Cascading Stylesheets
The C in CSS stands for ‘Cascading’. That’s just a fancy way to say that browsers read CSS files from top to bottom – but it’s more complicated than that!
Here are the basics:
Order < Specificity < Inline < !important
When a browser looks at a stylesheet, it computes each rule in order, replacing rules as it goes. However, if it runs into a rule which is more specific, has a special !important marker, or is embedded directly in the HTML it will not overwrite. Don’t worry too much if that didn’t make sense.
Lets look at each tier:
Order
Styles which are defined last will be the styles ultimately displayed by the browser. For example, if I tell the browser to make the text blue on line 2 and then I say to make the text red on line 6, browsers will make the text red.
p {
color: blue;
}
p {
color: red;
}
/* p will be red */
(also true of rules in the same block)
p {
color: blue;
color: red;
}
/* p will be red */
This also applies to the order in which different stylesheets are defined in the page. If you declare stylesheet 1 above stylesheet 2, all the rules defined in stylesheet 2 will take precedence over the rules in stylesheet 1.
Order is why we put our libraries first and the CSS we are actually writing last in <head>.
<link rel="stylesheet" type="text/css" href="bootstrap.min.css">
.
<link rel="stylesheet" type="text/css" href="main.css">
Another place this might trip someone up is in the html itself:
<p class="blue red">Text</p>
If two classes with the same level of priority are set on the same element, the one that comes last will be computed last. Therefore, the above text element will be red!
Specificity
What overrides what is all really complicated if you dig but the basics are simple. Specificity in CSS boils down to this:
The more specifically you select an element, the more priority your rule will have.
A handy flowchart:

An example:
<p id="section1" class="paragraph">Some text</p>
With a stylesheet that says:
#section1 {
color: red;
}
.paragraph {
color: blue;
}
p {
color: yellow;
}
Order would have us think the text will be yellow but it will in fact be red. This is because the #id is the most specific of the three. The second most specific is the class.
element < class < ID < Inline < !important
There can only be one element with a certain ID on a page and a class will generally only go on some elements. Selecting a whole type of elements is as unspecific as you can be, therefore it comes last.
But wait! This isn’t the only way to be specific in browserland. Lets look at some more code:
<p>Paragraph 1</p>
<div>
<p>Paragraph 2</p>
</div>
div p {
color: red;
}
p {
color: blue;
}
Paragraph 2 (and all other paragraphs on the page which haven’t been overwritten) will be blue. Paragraph 2 will be red because I specifically said that any p in a div should be red – this is more specific than just saying all p should be blue. Therefore it takes precedence.
Inline Styles
The only rules which can’t be overwritten by stylesheets (except with !important or this nifty trick) are inline styles. They look like this:
<p style="color: red">I am red</p>
Nowadays we try to avoid them as much as possible because they’re annoying to overwrite. One of my biggest pet peeves is using themes where the author makes heavy use of inline CSS. Avoid putting CSS directly into the HTML at all if you can.
!important
You can put !important before the semicolon to artificially bump up the priority of a rule. It will take precedence over everything (but follow the same rules of order and specificity if competing with another !important rule).
p {
color: blue !important;
}
Use this for debugging and replace it with a more specific expression once you figure out what’s wrong. Much like inline CSS, it’s better to avoid using it at all because it forces everyone else (potentially including your future self) to code around it if they can’t fix it with specificity.
Happy Coding!
Hopefully this will have given you a more intuitive understanding of how CSS works and will save you some pain debugging in the future. For further reading and a more in-depth guide I’d recommend the Mozilla Developer Network article on the subject.