CSS Inheritance, Cascade, and Specificity

Now that you're starting to get used to using some basic CSS rules, it's time to start learning the "big concepts" of CSS. Inheritance, the Cascade, and Specificity are the big three. Understanding these concepts will allow you to write very powerful stylesheets and also save time by writing fewer CSS rules.

Inheritance

In CSS, some styles are inherited down the HTML document tree while others are not.

While this can be confusing, the principle behind it is actually designed to allow you to write fewer CSS rules.

Inherited Styles

Styles that are inherited are generally related to the text styling of the document.

The font property is inherited. This is why we use the <body> element to attach our font styles.

The body element in our HTML is the parent of all of our other visible HTML elements. Setting the font property on the body element allows the rest of the document to inherit the font rule.

body {
   font: 1em/1.4 Helvetica, Verdana, sans-serif;
}

Using the rule above, all text (unless we specify otherwise) will be 1em with the line height scaled at 1.4 times the text height and be Helvetica or Verdana.

Styles That Are Not Inherited

Styles that are not inherited are usually related to the appearance of elements.

For example, the border property is not inherited, because it would not make sense. Remember what happens when we used the universal selector to set the border property?

Inheritance Reference Page

In general, you can just use common sense to figure out if a property is inherited or not. Think to yourself, "Would it make sense for this property to be inherited?"

If simple reasoning fails, the following CSS reference page lists many CSS properties. The right column indicates whether or not the property is inherited.


Specificity

CSS rules often conflict with one another. In fact, this is what we want. The trick is understanding how conflicting rules will apply.

Specificity is one of the ways that conflicting rules are applied.

Selectors have different values of importance (or specificity). Here is the short list (listed in order of importance):

  1. id selectors
  2. class and pseudo class selectors
  3. element selectors

If multiple CSS rules conflict with one another, the most important or specific selector is the one that will apply.

Calculating Specificity Level

Usually, we combine different types of selectors in our CSS to make the rules. We can use a relatively simple technique to rate the specificity level of each rule.

Assume we have the following HTML snippet:

<body class="home">
  <header id="navigation">
    <nav class="main-nav">
      <ul>
        <li class="home">Home</li>
        <li class="recipes">Recipes</li>
        <li class="tips">Tips</li>
        <li class="about">About</li>
      </ul>
    </nav>
  </header>
</body>

Now assume we have the following CSS rules (line numbers added for clarity):

1.   nav                     { color: red; }
2.   nav.main-nav            { color: blue; }
3.   header nav              { color: lime; }
4.   #navigation nav         { color: green; }
5.   header#navigation nav   { color: aqua; }
6.   body.home header#navigation nav.main-nav { color: purple; }

There is a simple scoring system for each style that you plug into a three-value layout like this:

A - B - C

Here's how the scoring system works:

  1. Add one to A for each ID in the selector
  2. Add one to B for each class or pseudo class in the selector
  3. Add one to C for each element name
  4. Read the result as a three-digit number

So, The CSS rules 1-6 in the above code all apply to the same nav element. Which one wins?

For those of you that are not so mathematically inclined, there's always this graphical method.


Cascade

We've already talked about how there can be many different sources of CSS styles. How do we know which one will be used?

In CSS, style sheets cascade by order of importance. If rules in different style sheets conflict with one another, the rule from the most important style sheet wins.

Below is a list of possible sources of a CSS rule. They are listed by order of importance. As the creator of the style sheet, you're the author.

  1. Author inline styles
  2. Author embedded styles (aka: internal style sheets)
  3. Author external style sheet
  4. User style sheet
  5. Default browser style sheet

We've already seen the cascade in action. All browsers have a default style sheet, which is designated as the least important.

Whenever we define a CSS rule, like font-family, we are actually overriding a default browser style sheet rule. This is the cascade in action.

What happens when conflicts occur?

There may be times when two or more declarations are applied to the same element. It is also possible that there may be a conflict between them. When conflicts like this occur, the declaration with the most weight is used. So, how is weight determined?

The Cascade Rules

  1. Find all declarations whose selectors match a particular element.
  2. Sort these declarations by weight and origin
  3. Sort the selectors by specificity
  4. Sort by order specified

For a complete description of these rules, see What happens when conflicts occur?

CSS Order Matters

In CSS, the order in which we specify our rules matters.

If a rule from the same style sheet, with the same level of specificity exists, the rule that is declared last in the CSS document will be the one that is applied.

An example will illustrate this best.

1.    p {color: black;}
2.    ul {border: 1px solid pink;}
3.    p.intro {color: brown;}
4.    p {color: red;}

In the code above, we have created rules for paragraphs to be three different colors. Clearly, these rules conflict with one another.

Rule #3 is the most specific because it specifies all paragraphs that also have the class attribute value of intro.

Rules #1 and #4 conflict. They are from the the same style sheet and they have the same level of specificity. If all else is equal in the cascade, we sort by order specified.

Rule #4 is declared last in the CSS document and therefore, overrides the previously declared Rule #1.