Chapter 1 - The C of CSS

Chapter 1 - The C of CSS

Lulu — You know, I already read some CSS on internet. I'd like to start with flex. It's trending!
Chrome — You see, that's the problem! Everyone wants to start with flex & grids. Fancy stuff! We won't do that. We're gonna dive right into the fundamentals first.
Lulu — You sound like a boring teacher.
Chrome — Well, all I can say is that it's gonna get interesting. And if you successfully complete the lesson, you can have some treat.
Lulu — That's like a good hooman. Let's start!

 

Anatomy of a Ruleset

Chrome — Okay, let's start with learning some terminology. The diagram below should do.
notion image
Chrome — Okay, so CSS is fundamentally about declaring rules.
Lulu — I declare all the rules in this house.
Chrome — Lulu, pay attention.
Lulu — I was just saying... (...meow meow).
Chrome — The most important part of CSS development is writing rules in a way that they are predictable.
Lulu — Just like I love it when things are predictable! I think CSS can be renamed to Cat Style Sheets.
Chrome — Yes, Lulu, I know you love things to be predictable. But you need to keep shut and listen. Without interrupting. Else we'll stop the lesson.
Lulu — Okay, don't be mad. I'll listen quietly. By the way, I'm doing it for the treats!

 
The understanding of cascade is going to help you understand how browsers think about and work with declarations. And how a browser decides which rule wins when there are two or three or more conflicting rules declared.
 
The cascade is made up of-
  1. Stylesheet Origin, i.e., where the styles are coming from.
  1. Selector Specificity, i.e., which selector takes precedence over which.
  1. Source Order, i.e., the order in which styles are declared in a sheet.
A browser considers these 3 aspects (in the same order) to determine the cascaded value. Let's talk about each of them in detail.
 

Style Sheet Origin

Primarily, there are two types of Style Sheets —
  1. User Agent (UA) Sheet - Provided by the browser(s).
  1. Author Styles - Ones that you write.
 
User Agent (UA) styles may vary slightly based on the taste of the browser that you are using but they usually do same things -
  1. Assign top and bottom margin to text elements- p, h1, h2, h3, h4, h5, h6.
  1. Left padding to list elements - ol, ul.
  1. Set default font size; which is usually 16px.
  1. Styling the links; i.e., the anchor tags (<a>).
A browser always starts with UA Styles. They are the origin with lowest priority.
 
Author Styles are the styles written by you. They usually consist of 3 types -
  1. External Stylesheets - The ones that you attach to your page using <link /> in <head> of your HTML document. Eg <link href="/css/main.css" rel="stylesheet" />
  1. Embedded Stylesheets - The styles you write that are sandwiched between <style></style> tags. Eg <style> body { margin: 0; padding: 0; } </style>
  1. Inline Stylesheets - Styles that you write as value of "style" attribute on elements/tags. Eg <p style="background: yellow;">Redo Your CSS</p>
Most of your page styles come from Author Styles; which are a higher priority origin. Hence, they'll always override UA styles.
Since most of your styles come from the same origin - Author Styles, a browser needs another way to find out which declaration wins when it encounters conflicting rules. That is done using Specificity of the selector.
 

Specificity

Understanding of Specificity is essential. Sadly, you'd find most of the developers skipping it when they're learning CSS.
A browser evaluates specificity based on -
  1. Inline Styles
  1. Selector Used
 
But let’s deal with another important concept before that.
!important declarations
A declaration can be marked “!important” to increase its priority value (usually making it top priority declaration). You do that by adding “!important” before semi-colon (;) in a declaration.
For example, color : black !important;
 
Inline Styles
Continuing on specificity, we need to understand "inline" styles because that is the first deciding factor on specificity.
Inline Styles or Inline Stylesheet are effectively “scoped” styles, since they’re applied directly to the element.
They override every style declaration from external or embedded style sheets except the “!important” ones.
However, if “!important” is used in inline styles, nothing overrides that.
 
notion image
 
Selector Specificity
Understand this with this example - a selector with two classes has higher specificity than one with single class.
Different selectors have different specificities. An ID selector has higher specificity than a class selector and a class selector has a higher specificity than a tag selector.
When deciding which selector wins, the browsers usually zero it down to this -
  • More IDs win;
  • If IDs result in tie, more classes win;
  • If classes result in tie, more tags win.
 
Note — Pseudo selectors (like :hover, etc) have same specificity as classes. The universal selector (*) and combinators (>, +, ~) have no effect on specificity.
 

Notation for Specificity

The notation for Specificity is given by -
(INLINE, IDs, CLASSes, TAGs)
However, INLINE is usually omitted and we're left with (IDs, CLASSes, TAGs).
 
Hence, a specificity of (1, 2, 0) wins over (0, 3, 0). Or (0, 1, 1) wins over (0, 1, 0).
 
Also understand this -
  • "#button" has a specificity of (1, 0, 0).
  • ".button" has a specificity of (0, 1, 0). But,
  • ".container a" & "a.link" both have a specificity of (0, 1, 1). The order doesn't make any difference. It's always about the number of tags, classes or IDs in use.
 

Lulu — What if two selectors have same specificity? Say (0, 1, 0) and (0, 1, 0).
Chrome — That’s indeed a very good question, Lulu. We are coming to it - “Source Order”.
Lulu — I told you I’m a smart cat!

 

Source Order

If two selectors have same specificity, then whichever rule is declared last, wins.
In fact, that’s the reason we declare rules for anchor tag (<a>) in order -
  • :link
  • :visited
  • :hover
  • :active
Since all pseudo selectors have same specificity as a class, the one which comes last will win.
 

Rule of Thumb

  1. Try not to use IDs in selectors.
  1. Try avoiding "!important".
That's because both make it difficult to override the previously assigned values. In large codebases, you'd always want to compose styles and that requires easy overriding. So try to keep the Specificity as low as possible.

 
Chrome - Once you understand this, you won't really struggle with debugging CSS, trying to figure out the source of styles.
Lulu — Well, that wasn't so difficult! Chrome — Maybe you got a good teacher.
Lulu — Maybe you got a really good student! Now I need my treats. Chrome — Yeah, yeah...I know!