The Cascade and Specificity

The Cascade

An element receives its style from the following, in order:

  1. User-agent stylesheet (browser defaults)
  2. User-defined styles
  3. Author-defined styles
    1. External stylesheet
    2. <style> tag in the document
    3. style="" attribute on an element

Styles defined in lower-priority stylesheets will be in effect if they are not overidden by relatively higher-priority stylesheets.

That's the cascade.

The cascade is a double-edged sword.

It's powerful but can make debugging difficult.

Specificity

So...what happens where there are two selectors in the stylesheet that target the same elements and have conflicting style properties?


<span class="author">Mark Twain</span>
    

span {
  font-size: 12px;
}

.author {
  font-size: 10px;
}
    

The answer: the selector that is most specific wins. Since a class selector is more specific than an element selector, the text will have a font size of 10px.


<span class="author">Mark Twain</span>
    

span {
  font-size: 12px;
}

.author {
  font-size: 10px; /* I win! */
}
    

So how do we know whether a selector is more specific than another selector?

We can use the familiar concept of version numbers to calculate specificity.

Which version is higher, 1.30.4 or 2.1?

Assume that the following two selectors apply to the same anchor element:


.app nav.main > ul > li .active {
  color: lightblue;
}

header > nav:first-child a.active {
  color: goldenrod;
}
    

How can we figure out which color the link will be?

We use this template. Break the selector into simple selectors and count:

[ID].[class, psuedo-class, attribute].[type]

So, for our first selector, there are 0 ID selectors...

.app nav.main > ul > li .active

...3 class selectors...

.app nav.main > ul > li .active

... and 3 type selectors...

.app nav.main > ul > li .active

...for a total selector strength of 0.3.3.

Our second selector also has 0 ID selectors...

header > nav:first-child a.active

...2 class/pseudo-class selectors...

header > nav:first-child a.active

...and 3 type selectors...

header > nav:first-child a.active

...for a total selector strength of 0.2.3.

The first selector was slightly more specific, and therefore the link will be light blue.


.app nav.main > ul > li .active {
  color: lightblue; /* I win! */
}

header > nav:first-child a.active {
  color: goldenrod;
}
    

One final note about the cascade; suppose we altered the previous example as follows:


.app nav.main > ul > li .active {
  color: lightblue; /* I win! */
}

header > nav:first-child a.active {
  color: goldenrod; /* (overridden) */
  background-color: coral; /* I sill apply! */
}
    

That's the cascade again.

And what happens if two selectors have the same specificity?


li a.current {
  color: aqua;
}

nav.main a {
  color: crimson;
}
    

The one defined later wins.


li a.current {
  color: aqua;
}

nav.main a {
  color: crimson; /* I win! */
}
    

Inheritance

Certain styles are inherited from parent elements.

Given this CSS:


body { font-size: 24px; }
    

And this HTML:


...
<body>
  <p>Hi!</p>
</body>
...
    

The <p> tag inherits the font size from its parent, <body>.

Chrome DevTools