Jump to main content
Menu

The Cascade

Author, User, and Browser Style Information

  • Style information comes from 3 sources:
    • Author Styles (what we specify in our style sheets)
    • User Styles (user-created style sheets)
    • The browser's internal stylesheet(s)
  • Generally speaking (but consult the order effects section for a finer-grained analysis), if there is conflicting information across those 3 sources about what value goes with a particular property:
    • Author styles override user and browser styles
    • User styles override browser styles
  • Non-conflicting styles, along with the styles that override conflicting instructions, combine together to determine the final rendering.
  • One possible scenario:
    • Your style sheet indicates <h1> text should be black, while the user's style sheet specifies that <h1> text should be white. Your text color is used.
    • You didn't specify a background color behind that <h1> text, but the user specified that the background color should be black behind <h1>. Since there was no conflict on the background property, the user's background's color is used.
    • The result is black text on a black background.
  • In most cases, setting a background color for <body> is sufficient, although setting one for <div> and <td> (if data tables are used) covers even more situations.
  • The use of !important flips all of this around. Using !important in a user style sheet allows it to override the author's use of !important (and !important in a browser's internal style sheet overrides all the other sources using !important as well).

What is the Cascade?

  • The cascade is a set of guidelines governing how various rules (and style sheets) interact.
  • If there are two (or more) conflicting style instructions applied to a tag/element, the cascade determines which are used and which are ignored.
  • Every rule has some degree of weight or influence, determined by how it is specified in the CSS. This is referred to as its specificity, which is the priority it can claim over other rules.
  • When instructions in different rules conflict, the rule with the greater specificity is used.
  • Note that non-conflicting values combine together. The cascade and specificities only enter the picture if two rules disagree on a particular setting for a property.

The Wrong, But Mostly Workable, Way to Calculate Specificity

  • This entire section presents an incorrect way of determining specificities, but nonetheless an approach that works out most of the time.
  • Consider it the "heuristic system". A heuristic is a guideline or rule of thumb. Most of the time it gets you where you're going, until it doesn't.
  • In the heuristic system, single elements have a specificity of 1 (regardless of the element).
    /* specificity of 1 */
    blockquote {color: purple;}
    
  • Making a contextual selector by adding elements to a selector (without commas) increases specificity by 1 for each additional element.
  • Separating elements with commas results in each element having a separate specificity assigned.
    /* specificity of 3 */
    blockquote em strong {color: yellow;}
    
    /* each of the three elements has a specificity of 1 */
    blockquote, em, strong {color: yellow;}
    
    /* blockquote has a specificity of 1,
       'em strong' has a specificity of 2 */
    blockquote, em strong {color: yellow;}
    
  • Classes have a specificity of 10. The specificity of classes and other selectors combine in a cumulative (additive) fashion.
    /* specificity of 10 */
    .nav {color: blue;}
    
    /* specificity of 11 */
    p.nav {color: red;}
    
    /* specificity of 22 */
    p.nav strong.red {color: red;}
    
  • IDs have a specificity of 100. An ID should only be used once per page, so it makes sense that they should have greater specificity than most other rules. IDs also have a cumulative (additive) specificity when combined with other selectors.
    /* specificity of 100 */
    #nav {color: blue;}
    
    /* specificity of 101 */
    p#nav {color: blue;}
    
  • Inline styles have a specificity of 1000 because they are coded directly into the element.
  • Pseudo-classes (:link, :visited, :hover, :focus, :active) are treated like other classes; they have specificities of 10.

Summarizing the Heuristic System

Selector / Method Specificity
Each element specified 1
Classes 10
Pseudo-classes 10
IDs 100
Inline styles 1000
!important 10,000

The Correct Model and Specificities

  • Specificities are actually broken up into four digits, separated either by commas or hyphens.
    • The first digit is whether the implementation is inline CSS, so it is a 1 (it is inline) or 0 (not inline).
    • The second digit is the number of IDs in the selector.
    • The third digit is the number of classes in the selector.
    • The fourth digit is the number of elements in the selector.
  • So an inline style has a specificity of 1,0,0,0 (or 1-0-0-0). In the heuristic system we call that 1000.
  • A single ID selector has a specifity of 0,1,0,0 (or 0-1-0-0). In the heuristic system we call that 100.
  • Two ID's (e.g., #topNav #currentNavItem) is 0,2,0,0 (or 0-2-0-0). In the heuristic system we call that 200.
  • Classes or pseudo-class have a specificity of 0,0,1,0 (or 0-0-1-0). In the heuristic system we call that 10.
  • An element selector or pseudo-element has a specificity of 0,0,0,1 (or 0-0-0-1). In the heuristic system we call that 1.
  • The following selector:
    p#nav ul.list {color: green;}
    

    Has a specificity of 0,1,1,2 (or 0-1-1-2). In the heuristic system we call that 112.

  • The following selector:
    #masthead #topnav .subitem .current {color: blue;}
    

    Has a specificity of 0,2,2,0 (or 0-2-2-0). In the heuristic system we call that 220.

  • So why is the heuristic system problematic?
    • Because it suggests that if you stack enough of a certain type of selector you can overcome another type of selector's specificity.
    • If your perspective is that classes are each 10, and an ID is 100, then if you chain 11 classes together you will have 110, and you will override the ID.
    • Or 11 descendant element selectors (space-separated selectors, such as 'body div div div div div div div nav ul li') will override a class.
    • Unfortunately, that's not how it works. Those experiments will fail. IDs are in a separate and higher order part of the calculation than classes. Classes are in a separate and higher order part of the calculation than element selectors. And that is where the wrong way of thinking about the cascade leads you astray.

The Use of !important

  • Inserting !important into a declaration (property: value pair) just prior to the closing semicolon (;) does just that, giving that instruction a specificity of 1,0,0,0,0 (or 1-0-0-0-0), with the value adjusted a bit more based on the selector used. In the heuristic system, we consider this as 10,000.
    /* specificity of 1,0,0,1,1 for the red color;
       the #fff background has a specificity of 0,0,1,1 */
    p.nav {background: #fff; color: red !important;}
    
  • Considerations / Warnings:
    • Be sure to correctly place !important or you risk invalidating the entire rule.
    • Use this only when absolutely necessary. It is the "nuclear option", and the only way it gets overcome is by another !important whose selector bumps its specificity even higher.
    • Often you can achieve your goal by slightly increasing selector specificity. You don't need this much firepower. Developers possessing a limited familiarity with the cascade use !important frequently and they are laying the groundwork for future headaches.

Inheriting Style Information

  • In some cases you will have tags (such as <em>) that have no rules applied to them.
  • If <em> is nested within another element (such as <h1>) that does have rules established, the <em> will inherit the same rules from its parent (and other elements even further out that hold the <h1> and <em>).

Example of Inherited Styles

<p style="color: blue; font-size: 1.1rem;">Hello <em>class</em></p>

The <em> has no rules defined so it renders as:

Hello class

The <em> inherits the blue color and the font size from the outer set of tags.

Null Specificity

  • When inheriting style information from an outer element, those inherited styles have a null specificity, no matter how strong the specificity is for that surrounding element.
  • Any rule with a specificity of 0,0,0,1 or more can override the inherited styles, as long as there are conflicting values. The only selector with 0 specificity is the universal selector, so it would not overcome inherited specificity.

Example of Inherited Styles Being Overridden

<p style="color: blue; font-size: 1.1rem;">Hello
<em style="color: red;">class</em></p>

The <em> has a conflicting color value defined so it renders as:

Hello class

The word 'class' becomes red because the specificity for the red color is 1,0,0,0 (due to it coming from an inline style for <em>), which is greater than the inherited null specificity from the <p> tag for the blue color.

So elements will inherit the values of parent elements unless they have their own conflicting values specified, in which case those conflicting values will go into effect.

Failed Inheritance

  • Many browsers fail to inherit style information properly from <body> into form elements, requiring those styles to be specifically applied to the form elements in the style sheet.
  • Testing cross-browser and cross-platform is essential because it identifies any issues with inheritance that need to be addressed.

Order Effects

  • What if you have two conflicting rules with the same specificity?
    • The one appearing later in the style sheet is given priority in the cascade, as it is closer to the point of rendering.
    • A rule appearing later in the same embedded, inline, or external style sheet will override what was specified previously.
    • When calculating order external style sheets come before embedded styles, which come before inline styles.
  • In the bigger picture of conflicting styles, the following hierarchy exists for determining which styles take precedence:
    1. Browser styles with !important
    2. User styles with !important
    3. Author styles with !important
    4. Author styles
    5. User styles
    6. Browser styles
  • In cases where you are bringing in other stylesheets (perhaps for a library, framework, or a user interface component), be sure to call your external stylesheet last. Why? Because when the specificities match, your CSS will be used. And that's probably what you want. Then there's less code for you to write, because you're not having to bump up your specificities to override the other stylesheets.