Thursday, November 7, 2013

CSS specificity hierarchy: what you need to know

Ryan Boudreaux covers the basics about CSS specificity hierarchy in an effort to make this tricky concept easier to understand.

If a CSS rule doesn't seem to work when it looks like it should and your code appears to be written correctly, or perhaps an element you're trying to style won't apply in any browser, your CSS rules are suffering from a CSS specificity conflict. While the concept isn't new to the web developer landscape, it's still probably one of the trickiest to grasp. I'll explain the CSS specificity hierarchy in a way that hopefully makes it easier to understand and then present several examples.

CSS specificity hierarchy

Specificity as stipulated by the W3C is calculated by first separating out the CSS selectors and rules into four categories or groups, and then assigning each group a ranking that allocates a weighted value. For graphical representation purposes, the first categorized grouping on the left side has a higher specificity value, and as the groupings move from left to right, the specificity values continue to decrease, with the last grouping having the least specificity value. The specificity is based only on the form of the selector.

For each CSS rule, you then concatenate the four figures A-B-C-D into a simple mnemonic large-base numbering system for notational purposes to determine the specificity value. The four groupings of selectors and their associated specificity values and optional value expressions are listed below.

The W3C calculates a selector's specificity as follows:

  • A. Count if an element has an in-line style rule and apply the value 1,0,0,0 or A=1, B=0, C=0, D=0 or x,0,0,0.
  • B. Count the number of ID attributes in the selector and apply the value 0,1,0,0 for each or A=0, B=1, C=0, D=0 or 0,x,0,0.
  • C. Count the number of classes, pseudo-classes, and other attributes in the selector and apply the value 0,0,1,0 for each or A=0, B=0, C=1, D=0 or 0,0,x,0.
  • D. Count the number of element names and pseudo-elements in the selector and apply the value 0,0,0,1 for each or A=0, B=0, C=0, D=1 or 0,0,0,x.
With artistic license and inspiration from the post by Chris Coyier on the subject, my graphic in Figure A illustrates the CSS selectors groupings and specificity, showing their associated placement, their associated character figure, an example of each type of selector, the selector type, and its place along the specificity scale.

Figure A

Given the nature of CSS specificity, the in-line style attributes always win and override any other attribute or elements. Any ID attribute will always outdo a class or pseudo-class attribute; in fact, any number of class attributes will always be overruled by any one ID. In effect, a selector with a higher specificity value will always trump a selector with a lower specificity value.

Examples of CSS specificity

The examples below will help to illustrate each of the CSS selectors and specificity in action.

Color attribute within an in-line style overrides paragraph element in external CSS

The in-line style color attribute for the green shaded paragraph content is illustrated in the code snippet:

This example of in-line style has a specificity value of 1,0,0,0 and will override any local or external CSS that is applied for the color attribute within that paragraph element. Even if we put in a paragraph element style within any external CSS with a color attribute, it will always remain the green shade for that paragraph. Because an element has a specificity value of 0,0,0,1, in this case the paragraph element gets overridden by the in-line style with a specificity value of 1,0,0,0.

In the example above, I set the sample paragraph with the in-line style and then applied a blue color to all paragraph elements within the external style sheet. The code snippet of the external CSS and the resulting output for both the in-line style and the paragraph element are displayed in Figure B as viewed in the Chrome browser.
Figure B
p { color: #06F; }


ID attribute overrides class attribute

In this example I demonstrate how an ID attribute will override a class attribute linked from an external CSS file while applied to a sample
container. The following two CSS code snippets for the "sidebar" offer two distinctly different styles.

The ID: 
#sidebarID { float: left; width: 50%; background:#0FC; padding-bottom: 5px;}
The Class: 
.sidebar1 { float: left; width: 25%; background: #CCC; padding-bottom: 10px; }
And the following HTML code snippet for the
is displayed below:

When both the Class and ID are applied to the section as coded in the HTML displayed above, the ID selector wins out since it has a specificity value of 0,1,0,0, and the Class selector has a value of 0,0,1,0. The resulting
as displayed in the Chrome browser is displayed in Figure C with the overriding ID selector applied.

Figure C

When the ID is not applied and the Class is called within the
by itself, it results in the following as displayed in the Chrome browser (Figure D).

Figure D

More CSS specificity example calculations

For demonstration purposes I will list a few examples of CSS selector combinations and their resulting specificity outcomes; this will also help in understanding how the values are applied in particular situations and sequences. These sample CSS selectors can be found in the CSS Specificity Calculator.

html > body - Two elements represented as a specificity value of  0,0,0,2.
#body -- One ID represented as a specificity value of 0,1,0,0.
#body.frontpage.default -- One ID and two classes represented as a specificity value of 0,1,2,0.

div#main-content a:focus -- One ID, one class, and two elements represented as 0,1,1,2. -- 42 classes represented as 0,0,42,0.

Additional resources about CSS specificity rules

  • CSS Specificity Calculator: The calculator has its limitations as it cannot include in-line styles; however, you can paste CSS snippets from your code and run the calculator to view the output, with options to show the details of how the results were calculated.
  • Calculating a selector's specificity: This is the W3C specification for calculating CSS selectors specificity.
  • CSS Specificity: The site provides a unique infographic with icons representing various combinations of selectors along with a legend, an About section, and links to the CSS Dev Conference.